| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  |  * This file contains the abstract XtoolsController, which all other controllers will extend. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | declare(strict_types=1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | namespace AppBundle\Controller; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | use AppBundle\Exception\XtoolsHttpException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | use AppBundle\Helper\I18nHelper; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | use AppBundle\Model\Page; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | use AppBundle\Model\Project; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | use AppBundle\Model\User; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | use AppBundle\Repository\PageRepository; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | use AppBundle\Repository\ProjectRepository; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | use AppBundle\Repository\UserRepository; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | use DateTime; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | use Doctrine\DBAL\DBALException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | use Symfony\Bundle\FrameworkBundle\Controller\Controller; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | use Symfony\Component\DependencyInjection\ContainerInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | use Symfony\Component\HttpFoundation\Cookie; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | use Symfony\Component\HttpFoundation\JsonResponse; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | use Symfony\Component\HttpFoundation\Request; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | use Symfony\Component\HttpFoundation\RequestStack; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  | use Symfony\Component\HttpFoundation\Response; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | use Symfony\Component\HttpKernel\Exception\HttpException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |  * XtoolsController supplies a variety of methods around parsing and validating parameters, and initializing | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |  * Project/User instances. These are used in other controllers in the AppBundle\Controller namespace. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |  * @abstract | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  | abstract class XtoolsController extends Controller | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |     /** @var I18nHelper i18n helper. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |     protected $i18n; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |     /** @var Request The request object. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |     protected $request; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |     /** @var string Name of the action within the child controller that is being executed. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 |  |  |     protected $controllerAction; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |     /** @var array Hash of params parsed from the Request. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |     protected $params; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |     /** @var bool Whether this is a request to an API action. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |     protected $isApi; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |     /** @var Project Relevant Project parsed from the Request. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |     protected $project; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |     /** @var User Relevant User parsed from the Request. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |     protected $user; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |     /** @var Page Relevant Page parsed from the Request. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |     protected $page; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |     /** @var int|false Start date parsed from the Request. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |     protected $start = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |     /** @var int|false End date parsed from the Request. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |     protected $end = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |      * Default days from current day, to use as the start date if none was provided. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |      * If this is null and $maxDays is non-null, the latter will be used as the default. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |      * Is public visibility evil here? I don't think so. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |      * @var int|null | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |     public $defaultDays = null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |      * Maximum number of days allowed for the given date range. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |      * Set this in the controller's constructor to enforce the given date range to be within this range. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |      * This will be used as the default date span unless $defaultDays is defined. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |      * @see XtoolsController::getUnixFromDateParams() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |      * @var int|null | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |     public $maxDays = null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |     /** @var int|string|null Namespace parsed from the Request, ID as int or 'all' for all namespaces. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |     protected $namespace; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |     /** @var int|false Unix timestamp. Pagination offset that substitutes for $end. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |     protected $offset = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |     /** @var int Number of results to return. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |     protected $limit; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |     /** @var bool Is the current request a subrequest? */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |     protected $isSubRequest; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |      * Stores user preferences such default project. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |      * This may get altered from the Request and updated in the Response. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |      * @var array | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |     protected $cookies = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |         'XtoolsProject' => null, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |     ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |      * This activates the 'too high edit count' functionality. This property represents the | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |      * action that should be redirected to if the user has too high of an edit count. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |      * @var string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |     protected $tooHighEditCountAction; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |     /** @var array Actions that are exempt from edit count limitations. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |     protected $tooHighEditCountActionBlacklist = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |      * Actions that require the target user to opt in to the restricted statistics. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |      * @see https://www.mediawiki.org/wiki/XTools/Edit_Counter#restricted_stats | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |      * @var string[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |     protected $restrictedActions = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |      * XtoolsController::validateProject() will ensure the given project matches one of these domains, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |      * instead of any valid project. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |      * @var string[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |     protected $supportedProjects; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |      * Require the tool's index route (initial form) be defined here. This should also | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |      * be the name of the associated model, if present. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |      * @return string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |     abstract protected function getIndexRoute(): string; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 |  |  |      * XtoolsController constructor. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |      * @param RequestStack $requestStack | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 |  |  |      * @param ContainerInterface $container | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 |  |  |      * @param I18nHelper $i18n | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 140 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 141 |  |  |     public function __construct(RequestStack $requestStack, ContainerInterface $container, I18nHelper $i18n) | 
            
                                                                        
                            
            
                                    
            
            
                | 142 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 143 |  |  |         $this->request = $requestStack->getCurrentRequest(); | 
            
                                                                        
                            
            
                                    
            
            
                | 144 |  |  |         $this->container = $container; | 
            
                                                                        
                            
            
                                    
            
            
                | 145 |  |  |         $this->i18n = $i18n; | 
            
                                                                        
                            
            
                                    
            
            
                | 146 |  |  |         $this->params = $this->parseQueryParams(); | 
            
                                                                        
                            
            
                                    
            
            
                | 147 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 148 |  |  |         // Parse out the name of the controller and action. | 
            
                                                                        
                            
            
                                    
            
            
                | 149 |  |  |         $pattern = "#::([a-zA-Z]*)Action#"; | 
            
                                                                        
                            
            
                                    
            
            
                | 150 |  |  |         $matches = []; | 
            
                                                                        
                            
            
                                    
            
            
                | 151 |  |  |         // The blank string here only happens in the unit tests, where the request may not be made to an action. | 
            
                                                                        
                            
            
                                    
            
            
                | 152 |  |  |         preg_match($pattern, $this->request->get('_controller') ?? '', $matches); | 
            
                                                                        
                            
            
                                    
            
            
                | 153 |  |  |         $this->controllerAction = $matches[1] ?? ''; | 
            
                                                                        
                            
            
                                    
            
            
                | 154 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 155 |  |  |         // Whether the action is an API action. | 
            
                                                                        
                            
            
                                    
            
            
                | 156 |  |  |         $this->isApi = 'Api' === substr($this->controllerAction, -3) || 'recordUsage' === $this->controllerAction; | 
            
                                                                        
                            
            
                                    
            
            
                | 157 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 158 |  |  |         // Whether we're making a subrequest (the view makes a request to another action). | 
            
                                                                        
                            
            
                                    
            
            
                | 159 |  |  |         $this->isSubRequest = $this->request->get('htmlonly') | 
            
                                                                        
                            
            
                                    
            
            
                | 160 |  |  |             || null !== $this->get('request_stack')->getParentRequest(); | 
            
                                                                        
                            
            
                                    
            
            
                | 161 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 162 |  |  |         // Disallow AJAX (unless it's an API or subrequest). | 
            
                                                                        
                            
            
                                    
            
            
                | 163 |  |  |         $this->checkIfAjax(); | 
            
                                                                        
                            
            
                                    
            
            
                | 164 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 165 |  |  |         // Load user options from cookies. | 
            
                                                                        
                            
            
                                    
            
            
                | 166 |  |  |         $this->loadCookies(); | 
            
                                                                        
                            
            
                                    
            
            
                | 167 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 168 |  |  |         // Set the class-level properties based on params. | 
            
                                                                        
                            
            
                                    
            
            
                | 169 |  |  |         if (false !== strpos(strtolower($this->controllerAction), 'index')) { | 
            
                                                                        
                            
            
                                    
            
            
                | 170 |  |  |             // Index pages should only set the project, and no other class properties. | 
            
                                                                        
                            
            
                                    
            
            
                | 171 |  |  |             $this->setProject($this->getProjectFromQuery()); | 
            
                                                                        
                            
            
                                    
            
            
                | 172 |  |  |         } else { | 
            
                                                                        
                            
            
                                    
            
            
                | 173 |  |  |             $this->setProperties(); // Includes the project. | 
            
                                                                        
                            
            
                                    
            
            
                | 174 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 175 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 176 |  |  |         // Check if the request is to a restricted API endpoint, where the target user has to opt-in to statistics. | 
            
                                                                        
                            
            
                                    
            
            
                | 177 |  |  |         $this->checkRestrictedApiEndpoint(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 |  |  |      * Check if the request is AJAX, and disallow it unless they're using the API or if it's a subrequest. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 |  |  |     private function checkIfAjax(): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  |         if ($this->request->isXmlHttpRequest() && !$this->isApi && !$this->isSubRequest) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  |             throw new HttpException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  |                 403, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 |  |  |                 $this->i18n->msg('error-automation', ['https://www.mediawiki.org/Special:MyLanguage/XTools/API']) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 |  |  |      * Check if the request is to a restricted API endpoint, and throw an exception if the target user hasn't opted-in. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 |  |  |      * @throws XtoolsHttpException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 |  |  |     private function checkRestrictedApiEndpoint(): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 |  |  |         $restrictedAction = in_array($this->controllerAction, $this->restrictedActions); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 |  |  |         if ($this->isApi && $restrictedAction && !$this->project->userHasOptedIn($this->user)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 |  |  |             throw new XtoolsHttpException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 |  |  |                 $this->i18n->msg('not-opted-in', [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  |                     $this->getOptedInPage()->getTitle(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 |  |  |                     $this->i18n->msg('not-opted-in-link') . | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 |  |  |                         ' <https://www.mediawiki.org/wiki/XTools/Edit_Counter#restricted_stats>', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 |  |  |                     $this->i18n->msg('not-opted-in-login'), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  |                 ]), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 |  |  |                 '', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 |  |  |                 $this->params, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 211 |  |  |                 true, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 212 |  |  |                 Response::HTTP_UNAUTHORIZED | 
            
                                                                                                            
                            
            
                                    
            
            
                | 213 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 214 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 215 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 216 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 217 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 218 |  |  |      * Get the path to the opt-in page for restricted statistics. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 219 |  |  |      * @return Page | 
            
                                                                                                            
                            
            
                                    
            
            
                | 220 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 221 |  |  |     protected function getOptedInPage(): Page | 
            
                                                                                                            
                            
            
                                    
            
            
                | 222 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 223 |  |  |         return $this->project | 
            
                                                                                                            
                            
            
                                    
            
            
                | 224 |  |  |             ->getRepository() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 225 |  |  |             ->getPage($this->project, $this->project->userOptInPage($this->user)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 226 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 227 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 228 |  |  |     /*********** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 229 |  |  |      * COOKIES * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 230 |  |  |      ***********/ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 231 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 232 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 233 |  |  |      * Load user preferences from the associated cookies. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 234 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 235 |  |  |     private function loadCookies(): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 236 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 237 |  |  |         // Not done for subrequests. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 238 |  |  |         if ($this->isSubRequest) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 239 |  |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 240 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 241 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 242 |  |  |         foreach (array_keys($this->cookies) as $name) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 243 |  |  |             $this->cookies[$name] = $this->request->cookies->get($name); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 244 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 245 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 246 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 247 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 248 |  |  |      * Set cookies on the given Response. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 249 |  |  |      * @param Response $response | 
            
                                                                                                            
                            
            
                                    
            
            
                | 250 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 251 |  |  |     private function setCookies(Response &$response): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 252 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 253 |  |  |         // Not done for subrequests. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 254 |  |  |         if ($this->isSubRequest) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 255 |  |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 256 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 257 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 258 |  |  |         foreach ($this->cookies as $name => $value) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 259 |  |  |             $response->headers->setCookie( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 260 |  |  |                 Cookie::create($name, $value) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 261 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 262 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 263 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 264 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 265 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 266 |  |  |      * Sets the project, with the domain in $this->cookies['XtoolsProject'] that will | 
            
                                                                                                            
                            
            
                                    
            
            
                | 267 |  |  |      * later get set on the Response headers in self::getFormattedResponse(). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 268 |  |  |      * @param Project $project | 
            
                                                                                                            
                            
            
                                    
            
            
                | 269 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 270 |  |  |     private function setProject(Project $project): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 271 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 272 |  |  |         // TODO: Remove after deprecated routes are retired. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 273 |  |  |         if (false !== strpos((string)$this->request->get('_controller'), 'GlobalContribs')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 274 |  |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 275 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 276 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 277 |  |  |         $this->project = $project; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 278 |  |  |         $this->cookies['XtoolsProject'] = $project->getDomain(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 279 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 280 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 281 |  |  |     /**************************** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 282 |  |  |      * SETTING CLASS PROPERTIES * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 283 |  |  |      ****************************/ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 284 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 285 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 286 |  |  |      * Normalize all common parameters used by the controllers and set class properties. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 287 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 288 |  |  |     private function setProperties(): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 289 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 290 |  |  |         $this->namespace = $this->params['namespace'] ?? null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 291 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 292 |  |  |         // Offset is given as ISO timestamp and is stored as a UNIX timestamp (or false). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 293 |  |  |         if (isset($this->params['offset'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 294 |  |  |             $this->offset = strtotime($this->params['offset']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 295 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 296 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 297 |  |  |         // Limit need to be an int. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 298 |  |  |         if (isset($this->params['limit'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 299 |  |  |             // Normalize. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 300 |  |  |             $this->params['limit'] = max(0, (int)$this->params['limit']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 301 |  |  |             $this->limit = $this->params['limit']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 302 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 303 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 304 |  |  |         if (isset($this->params['project'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 305 |  |  |             $this->setProject($this->validateProject($this->params['project'])); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 306 |  |  |         } elseif (null !== $this->cookies['XtoolsProject']) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 307 |  |  |             // Set from cookie. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 308 |  |  |             $this->setProject( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 309 |  |  |                 $this->validateProject($this->cookies['XtoolsProject']) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 310 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 311 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 312 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 313 |  |  |         if (isset($this->params['username'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 314 |  |  |             $this->user = $this->validateUser($this->params['username']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 315 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 316 |  |  |         if (isset($this->params['page'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 317 |  |  |             $this->page = $this->getPageFromNsAndTitle($this->namespace, $this->params['page']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 318 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 319 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 320 |  |  |         $this->setDates(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 321 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 322 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 323 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 324 |  |  |      * Set class properties for dates, if such params were passed in. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 325 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 326 |  |  |     private function setDates(): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 327 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 328 |  |  |         $start = $this->params['start'] ?? false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 329 |  |  |         $end = $this->params['end'] ?? false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 330 |  |  |         if ($start || $end || null !== $this->maxDays) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 331 |  |  |             [$this->start, $this->end] = $this->getUnixFromDateParams($start, $end); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 332 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 333 |  |  |             // Set $this->params accordingly too, so that for instance API responses will include it. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 334 |  |  |             $this->params['start'] = is_int($this->start) ? date('Y-m-d', $this->start) : false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 335 |  |  |             $this->params['end'] = is_int($this->end) ? date('Y-m-d', $this->end) : false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 336 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 337 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 338 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 339 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 340 |  |  |      * Construct a fully qualified page title given the namespace and title. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 341 |  |  |      * @param int|string $ns Namespace ID. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 342 |  |  |      * @param string $title Page title. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 343 |  |  |      * @param bool $rawTitle Return only the title (and not a Page). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 344 |  |  |      * @return Page|string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 345 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 346 |  |  |     protected function getPageFromNsAndTitle($ns, string $title, bool $rawTitle = false) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 347 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 348 |  |  |         if (0 === (int)$ns) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 349 |  |  |             return $rawTitle ? $title : $this->validatePage($title); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 350 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 351 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 352 |  |  |         // Prepend namespace and strip out duplicates. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 353 |  |  |         $nsName = $this->project->getNamespaces()[$ns] ?? $this->i18n->msg('unknown'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 354 |  |  |         $title = $nsName.':'.preg_replace('/^'.$nsName.':/', '', $title); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 355 |  |  |         return $rawTitle ? $title : $this->validatePage($title); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 356 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 357 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 358 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 359 |  |  |      * Get a Project instance from the project string, using defaults if the given project string is invalid. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 360 |  |  |      * @return Project | 
            
                                                                                                            
                            
            
                                    
            
            
                | 361 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 362 |  |  |     public function getProjectFromQuery(): Project | 
            
                                                                                                            
                            
            
                                    
            
            
                | 363 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 364 |  |  |         // Set default project so we can populate the namespace selector on index pages. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 365 |  |  |         // Defaults to project stored in cookie, otherwise project specified in parameters.yml. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 366 |  |  |         if (isset($this->params['project'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 367 |  |  |             $project = $this->params['project']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 368 |  |  |         } elseif (null !== $this->cookies['XtoolsProject']) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 369 |  |  |             $project = $this->cookies['XtoolsProject']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 370 |  |  |         } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 371 |  |  |             $project = $this->container->getParameter('default_project'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 372 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 373 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 374 |  |  |         $projectData = ProjectRepository::getProject($project, $this->container); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 375 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 376 |  |  |         // Revert back to defaults if we've established the given project was invalid. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 377 |  |  |         if (!$projectData->exists()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 378 |  |  |             $projectData = ProjectRepository::getProject( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 379 |  |  |                 $this->container->getParameter('default_project'), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 380 |  |  |                 $this->container | 
            
                                                                                                            
                            
            
                                    
            
            
                | 381 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 382 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 383 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 384 |  |  |         return $projectData; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 385 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 386 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 387 |  |  |     /************************* | 
            
                                                                                                            
                            
            
                                    
            
            
                | 388 |  |  |      * GETTERS / VALIDATIONS * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 389 |  |  |      *************************/ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 390 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 391 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 392 |  |  |      * Validate the given project, returning a Project if it is valid or false otherwise. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 393 |  |  |      * @param string $projectQuery Project domain or database name. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 394 |  |  |      * @return Project | 
            
                                                                                                            
                            
            
                                    
            
            
                | 395 |  |  |      * @throws XtoolsHttpException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 396 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 397 |  |  |     public function validateProject(string $projectQuery): Project | 
            
                                                                                                            
                            
            
                                    
            
            
                | 398 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 399 |  |  |         /** @var Project $project */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 400 |  |  |         $project = ProjectRepository::getProject($projectQuery, $this->container); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 401 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 402 |  |  |         // Check if it is an explicitly allowed project for the current tool. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 403 |  |  |         if (isset($this->supportedProjects) && !in_array($project->getDomain(), $this->supportedProjects)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 404 |  |  |             $this->throwXtoolsException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 405 |  |  |                 $this->getIndexRoute(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 406 |  |  |                 'error-authorship-unsupported-project', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 407 |  |  |                 [$this->params['project']], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 408 |  |  |                 'project' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 409 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 410 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 411 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 412 |  |  |         if (!$project->exists()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 413 |  |  |             $this->throwXtoolsException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 414 |  |  |                 $this->getIndexRoute(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 415 |  |  |                 'invalid-project', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 416 |  |  |                 [$this->params['project']], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 417 |  |  |                 'project' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 418 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 419 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 420 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 421 |  |  |         return $project; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 422 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 423 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 424 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 425 |  |  |      * Validate the given user, returning a User or Redirect if they don't exist. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 426 |  |  |      * @param string $username | 
            
                                                                                                            
                            
            
                                    
            
            
                | 427 |  |  |      * @return User | 
            
                                                                                                            
                            
            
                                    
            
            
                | 428 |  |  |      * @throws XtoolsHttpException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 429 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 430 |  |  |     public function validateUser(string $username): User | 
            
                                                                                                            
                            
            
                                    
            
            
                | 431 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 432 |  |  |         $user = UserRepository::getUser($username, $this->container); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 433 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 434 |  |  |         // Allow querying for any IP, currently with no edit count limitation... | 
            
                                                                                                            
                            
            
                                    
            
            
                | 435 |  |  |         // Once T188677 is resolved IPs will be affected by the EXPLAIN results. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 436 |  |  |         if ($user->isAnon()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 437 |  |  |             if ($user->isIpRange() && ) | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 438 |  |  |             return $user; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 439 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 440 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 441 |  |  |         $originalParams = $this->params; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 442 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 443 |  |  |         // Don't continue if the user doesn't exist. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 444 |  |  |         if ($this->project && !$user->existsOnProject($this->project)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 445 |  |  |             $this->throwXtoolsException($this->getIndexRoute(), 'user-not-found', [], 'username'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 446 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 447 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 448 |  |  |         // Reject users with a crazy high edit count. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 449 |  |  |         if (isset($this->tooHighEditCountAction) && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 450 |  |  |             !in_array($this->controllerAction, $this->tooHighEditCountActionBlacklist) && | 
            
                                                                                                            
                            
            
                                    
            
            
                | 451 |  |  |             $user->hasTooManyEdits($this->project) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 452 |  |  |         ) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 453 |  |  |             /** TODO: Somehow get this to use self::throwXtoolsException */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 454 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 455 |  |  |             // If redirecting to a different controller, show an informative message accordingly. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 456 |  |  |             if ($this->tooHighEditCountAction !== $this->getIndexRoute()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 457 |  |  |                 // FIXME: This is currently only done for Edit Counter, redirecting to Simple Edit Counter, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 458 |  |  |                 //   so this bit is hardcoded. We need to instead give the i18n key of the route. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 459 |  |  |                 $redirMsg = $this->i18n->msg('too-many-edits-redir', [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 460 |  |  |                     $this->i18n->msg('tool-simpleeditcounter'), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 461 |  |  |                 ]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 462 |  |  |                 $msg = $this->i18n->msg('too-many-edits', [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 463 |  |  |                     $this->i18n->numberFormat($user->maxEdits()), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 464 |  |  |                 ]).'. '.$redirMsg; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 465 |  |  |                 $this->addFlashMessage('danger', $msg); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 466 |  |  |             } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 467 |  |  |                 $this->addFlashMessage('danger', 'too-many-edits', [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 468 |  |  |                     $this->i18n->numberFormat($user->maxEdits()), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 469 |  |  |                 ]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 470 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 471 |  |  |                 // Redirecting back to index, so remove username (otherwise we'd get a redirect loop). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 472 |  |  |                 unset($this->params['username']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 473 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 474 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 475 |  |  |             // Clear flash bag for API responses, since they get intercepted in ExceptionListener | 
            
                                                                                                            
                            
            
                                    
            
            
                | 476 |  |  |             // and would otherwise be shown in subsequent requests. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 477 |  |  |             if ($this->isApi) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 478 |  |  |                 $this->get('session')->getFlashBag()->clear(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 479 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 480 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 481 |  |  |             throw new XtoolsHttpException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 482 |  |  |                 'User has made too many edits! Maximum '.$user->maxEdits(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 483 |  |  |                 $this->generateUrl($this->tooHighEditCountAction, $this->params), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 484 |  |  |                 $originalParams, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 485 |  |  |                 $this->isApi | 
            
                                                                                                            
                            
            
                                    
            
            
                | 486 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 487 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 488 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 489 |  |  |         return $user; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 490 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 491 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 492 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 493 |  |  |      * Get a Page instance from the given page title, and validate that it exists. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 494 |  |  |      * @param string $pageTitle | 
            
                                                                                                            
                            
            
                                    
            
            
                | 495 |  |  |      * @return Page | 
            
                                                                                                            
                            
            
                                    
            
            
                | 496 |  |  |      * @throws XtoolsHttpException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 497 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 498 |  |  |     public function validatePage(string $pageTitle): Page | 
            
                                                                                                            
                            
            
                                    
            
            
                | 499 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 500 |  |  |         $page = new Page($this->project, $pageTitle); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 501 |  |  |         $pageRepo = new PageRepository(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 502 |  |  |         $pageRepo->setContainer($this->container); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 503 |  |  |         $page->setRepository($pageRepo); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 504 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 505 |  |  |         if (!$page->exists()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 506 |  |  |             $this->throwXtoolsException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 507 |  |  |                 $this->getIndexRoute(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 508 |  |  |                 'no-result', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 509 |  |  |                 [$this->params['page'] ?? null], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 510 |  |  |                 'page' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 511 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 512 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 513 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 514 |  |  |         return $page; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 515 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 516 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 517 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 518 |  |  |      * Throw an XtoolsHttpException, which the given error message and redirects to specified action. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 519 |  |  |      * @param string $redirectAction Name of action to redirect to. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 520 |  |  |      * @param string $message i18n key of error message. Shown in API responses. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 521 |  |  |      *   If no message with this key exists, $message is shown as-is. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 522 |  |  |      * @param array $messageParams | 
            
                                                                                                            
                            
            
                                    
            
            
                | 523 |  |  |      * @param string $invalidParam This will be removed from $this->params. Omit if you don't want this to happen. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 524 |  |  |      * @throws XtoolsHttpException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 525 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 526 |  |  |     public function throwXtoolsException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 527 |  |  |         string $redirectAction, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 528 |  |  |         string $message, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 529 |  |  |         array $messageParams = [], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 530 |  |  |         ?string $invalidParam = null | 
            
                                                                                                            
                            
            
                                    
            
            
                | 531 |  |  |     ): void { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 532 |  |  |         $this->addFlashMessage('danger', $message, $messageParams); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 533 |  |  |         $originalParams = $this->params; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 534 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 535 |  |  |         // Remove invalid parameter if it was given. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 536 |  |  |         if (is_string($invalidParam)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 537 |  |  |             unset($this->params[$invalidParam]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 538 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 539 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 540 |  |  |         // We sometimes are redirecting to the index page, so also remove project (otherwise we'd get a redirect loop). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 541 |  |  |         /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 542 |  |  |          * FIXME: Index pages should have a 'nosubmit' parameter to prevent submission. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 543 |  |  |          * Then we don't even need to remove $invalidParam. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 544 |  |  |          * Better, we should show the error on the results page, with no results. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 545 |  |  |          */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 546 |  |  |         unset($this->params['project']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 547 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 548 |  |  |         // Throw exception which will redirect to $redirectAction. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 549 |  |  |         throw new XtoolsHttpException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 550 |  |  |             $this->i18n->msgIfExists($message, $messageParams), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 551 |  |  |             $this->generateUrl($redirectAction, $this->params), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 552 |  |  |             $originalParams, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 553 |  |  |             $this->isApi | 
            
                                                                                                            
                            
            
                                    
            
            
                | 554 |  |  |         ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 555 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 556 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 557 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 558 |  |  |      * Get the first error message stored in the session's FlashBag. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 559 |  |  |      * @return string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 560 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 561 |  |  |     public function getFlashMessage(): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 562 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 563 |  |  |         $key = $this->get('session')->getFlashBag()->get('danger')[0]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 564 |  |  |         $param = null; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 565 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 566 |  |  |         if (is_array($key)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 567 |  |  |             [$key, $param] = $key; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 568 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 569 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 570 |  |  |         return $this->render('message.twig', [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 571 |  |  |             'key' => $key, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 572 |  |  |             'params' => [$param], | 
            
                                                                                                            
                            
            
                                    
            
            
                | 573 |  |  |         ])->getContent(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 574 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 575 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 576 |  |  |     /****************** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 577 |  |  |      * PARSING PARAMS * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 578 |  |  |      ******************/ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 579 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 580 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 581 |  |  |      * Get all standardized parameters from the Request, either via URL query string or routing. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 582 |  |  |      * @return string[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 583 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 584 |  |  |     public function getParams(): array | 
            
                                                                                                            
                            
            
                                    
            
            
                | 585 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 586 |  |  |         $paramsToCheck = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 587 |  |  |             'project', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 588 |  |  |             'username', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 589 |  |  |             'namespace', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 590 |  |  |             'page', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 591 |  |  |             'categories', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 592 |  |  |             'group', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 593 |  |  |             'redirects', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 594 |  |  |             'deleted', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 595 |  |  |             'start', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 596 |  |  |             'end', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 597 |  |  |             'offset', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 598 |  |  |             'limit', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 599 |  |  |             'format', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 600 |  |  |             'tool', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 601 |  |  |             'tools', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 602 |  |  |             'q', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 603 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 604 |  |  |             // Legacy parameters. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 605 |  |  |             'user', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 606 |  |  |             'name', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 607 |  |  |             'article', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 608 |  |  |             'wiki', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 609 |  |  |             'wikifam', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 610 |  |  |             'lang', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 611 |  |  |             'wikilang', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 612 |  |  |             'begin', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 613 |  |  |         ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 614 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 615 |  |  |         /** @var string[] $params Each parameter that was detected along with its value. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 616 |  |  |         $params = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 617 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 618 |  |  |         foreach ($paramsToCheck as $param) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 619 |  |  |             // Pull in either from URL query string or route. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 620 |  |  |             $value = $this->request->query->get($param) ?: $this->request->get($param); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 621 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 622 |  |  |             // Only store if value is given ('namespace' or 'username' could be '0'). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 623 |  |  |             if (null !== $value && '' !== $value) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 624 |  |  |                 $params[$param] = rawurldecode((string)$value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 625 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 626 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 627 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 628 |  |  |         return $params; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 629 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 630 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 631 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 632 |  |  |      * Parse out common parameters from the request. These include the 'project', 'username', 'namespace' and 'page', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 633 |  |  |      * along with their legacy counterparts (e.g. 'lang' and 'wiki'). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 634 |  |  |      * @return string[] Normalized parameters (no legacy params). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 635 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 636 |  |  |     public function parseQueryParams(): array | 
            
                                                                                                            
                            
            
                                    
            
            
                | 637 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 638 |  |  |         /** @var string[] $params Each parameter and value that was detected. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 639 |  |  |         $params = $this->getParams(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 640 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 641 |  |  |         // Covert any legacy parameters, if present. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 642 |  |  |         $params = $this->convertLegacyParams($params); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 643 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 644 |  |  |         // Remove blank values. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 645 |  |  |         return array_filter($params, function ($param) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 646 |  |  |             // 'namespace' or 'username' could be '0'. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 647 |  |  |             return null !== $param && '' !== $param; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 648 |  |  |         }); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 649 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 650 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 651 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 652 |  |  |      * Get Unix timestamps from given start and end string parameters. This also makes $start $maxDays before | 
            
                                                                                                            
                            
            
                                    
            
            
                | 653 |  |  |      * $end if not present, and makes $end the current time if not present. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 654 |  |  |      * The date range will not exceed $this->maxDays days, if this public class property is set. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 655 |  |  |      * @param int|string|false $start Unix timestamp or string accepted by strtotime. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 656 |  |  |      * @param int|string|false $end Unix timestamp or string accepted by strtotime. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 657 |  |  |      * @return int[] Start and end date as UTC timestamps. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 658 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 659 |  |  |     public function getUnixFromDateParams($start, $end): array | 
            
                                                                                                            
                            
            
                                    
            
            
                | 660 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 661 |  |  |         $today = strtotime('today midnight'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 662 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 663 |  |  |         // start time should not be in the future. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 664 |  |  |         $startTime = min( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 665 |  |  |             is_int($start) ? $start : strtotime((string)$start), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 666 |  |  |             $today | 
            
                                                                                                            
                            
            
                                    
            
            
                | 667 |  |  |         ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 668 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 669 |  |  |         // end time defaults to now, and will not be in the future. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 670 |  |  |         $endTime = min( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 671 |  |  |             (is_int($end) ? $end : strtotime((string)$end)) ?: $today, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 672 |  |  |             $today | 
            
                                                                                                            
                            
            
                                    
            
            
                | 673 |  |  |         ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 674 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 675 |  |  |         // Default to $this->defaultDays or $this->maxDays before end time if start is not present. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 676 |  |  |         $daysOffset = $this->defaultDays ?? $this->maxDays; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 677 |  |  |         if (false === $startTime && is_int($daysOffset)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 678 |  |  |             $startTime = strtotime("-$daysOffset days", $endTime); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 679 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 680 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 681 |  |  |         // Default to $this->defaultDays or $this->maxDays after start time if end is not present. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 682 |  |  |         if (false === $end && is_int($daysOffset)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 683 |  |  |             $endTime = min( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 684 |  |  |                 strtotime("+$daysOffset days", $startTime), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 685 |  |  |                 $today | 
            
                                                                                                            
                            
            
                                    
            
            
                | 686 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 687 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 688 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 689 |  |  |         // Reverse if start date is after end date. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 690 |  |  |         if ($startTime > $endTime && false !== $startTime && false !== $end) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 691 |  |  |             $newEndTime = $startTime; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 692 |  |  |             $startTime = $endTime; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 693 |  |  |             $endTime = $newEndTime; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 694 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 695 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 696 |  |  |         // Finally, don't let the date range exceed $this->maxDays. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 697 |  |  |         $startObj = DateTime::createFromFormat('U', (string)$startTime); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 698 |  |  |         $endObj = DateTime::createFromFormat('U', (string)$endTime); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 699 |  |  |         if (is_int($this->maxDays) && $startObj->diff($endObj)->days > $this->maxDays) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 700 |  |  |             // Show warnings that the date range was truncated. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 701 |  |  |             $this->addFlashMessage('warning', 'date-range-too-wide', [$this->maxDays]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 702 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 703 |  |  |             $startTime = strtotime("-$this->maxDays days", $endTime); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 704 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 705 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 706 |  |  |         return [$startTime, $endTime]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 707 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 708 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 709 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 710 |  |  |      * Given the params hash, normalize any legacy parameters to their modern equivalent. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 711 |  |  |      * @param string[] $params | 
            
                                                                                                            
                            
            
                                    
            
            
                | 712 |  |  |      * @return string[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 713 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 714 |  |  |     private function convertLegacyParams(array $params): array | 
            
                                                                                                            
                            
            
                                    
            
            
                | 715 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 716 |  |  |         $paramMap = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 717 |  |  |             'user' => 'username', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 718 |  |  |             'name' => 'username', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 719 |  |  |             'article' => 'page', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 720 |  |  |             'begin' => 'start', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 721 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 722 |  |  |             // Copy super legacy project params to legacy so we can concatenate below. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 723 |  |  |             'wikifam' => 'wiki', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 724 |  |  |             'wikilang' => 'lang', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 725 |  |  |         ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 726 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 727 |  |  |         // Copy legacy parameters to modern equivalent. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 728 |  |  |         foreach ($paramMap as $legacy => $modern) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 729 |  |  |             if (isset($params[$legacy])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 730 |  |  |                 $params[$modern] = $params[$legacy]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 731 |  |  |                 unset($params[$legacy]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 732 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 733 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 734 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 735 |  |  |         // Separate parameters for language and wiki. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 736 |  |  |         if (isset($params['wiki']) && isset($params['lang'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 737 |  |  |             // 'wikifam' will be like '.wikipedia.org', vs just 'wikipedia', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 738 |  |  |             // so we must remove leading periods and trailing .org's. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 739 |  |  |             $params['project'] = rtrim(ltrim($params['wiki'], '.'), '.org').'.org'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 740 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 741 |  |  |             /** @var string[] $languagelessProjects Projects for which there is no specific language association. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 742 |  |  |             $languagelessProjects = $this->container->getParameter('app.multilingual_wikis'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 743 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 744 |  |  |             // Prepend language if applicable. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 745 |  |  |             if (isset($params['lang']) && !in_array($params['wiki'], $languagelessProjects)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 746 |  |  |                 $params['project'] = $params['lang'].'.'.$params['project']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 747 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 748 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 749 |  |  |             unset($params['wiki']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 750 |  |  |             unset($params['lang']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 751 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 752 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 753 |  |  |         return $params; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 754 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 755 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 756 |  |  |     /************************ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 757 |  |  |      * FORMATTING RESPONSES * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 758 |  |  |      ************************/ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 759 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 760 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 761 |  |  |      * Get the rendered template for the requested format. This method also updates the cookies. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 762 |  |  |      * @param string $templatePath Path to template without format, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 763 |  |  |      *   such as '/editCounter/latest_global'. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 764 |  |  |      * @param array $ret Data that should be passed to the view. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 765 |  |  |      * @return Response | 
            
                                                                                                            
                            
            
                                    
            
            
                | 766 |  |  |      * @codeCoverageIgnore | 
            
                                                                                                            
                            
            
                                    
            
            
                | 767 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 768 |  |  |     public function getFormattedResponse(string $templatePath, array $ret): Response | 
            
                                                                                                            
                            
            
                                    
            
            
                | 769 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 770 |  |  |         $format = $this->request->query->get('format', 'html'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 771 |  |  |         if ('' == $format) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 772 |  |  |             // The default above doesn't work when the 'format' parameter is blank. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 773 |  |  |             $format = 'html'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 774 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 775 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 776 |  |  |         // Merge in common default parameters, giving $ret (from the caller) the priority. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 777 |  |  |         $ret = array_merge([ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 778 |  |  |             'project' => $this->project, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 779 |  |  |             'user' => $this->user, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 780 |  |  |             'page' => $this->page, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 781 |  |  |             'namespace' => $this->namespace, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 782 |  |  |             'start' => $this->start, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 783 |  |  |             'end' => $this->end, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 784 |  |  |         ], $ret); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 785 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 786 |  |  |         $formatMap = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 787 |  |  |             'wikitext' => 'text/plain', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 788 |  |  |             'csv' => 'text/csv', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 789 |  |  |             'tsv' => 'text/tab-separated-values', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 790 |  |  |             'json' => 'application/json', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 791 |  |  |         ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 792 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 793 |  |  |         $response = new Response(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 794 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 795 |  |  |         // Set cookies. Note this must be done before rendering the view, as the view may invoke subrequests. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 796 |  |  |         $this->setCookies($response); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 797 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 798 |  |  |         // If requested format does not exist, assume HTML. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 799 |  |  |         if (false === $this->get('twig')->getLoader()->exists("$templatePath.$format.twig")) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 800 |  |  |             $format = 'html'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 801 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 802 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 803 |  |  |         $response = $this->render("$templatePath.$format.twig", $ret, $response); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 804 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 805 |  |  |         $contentType = $formatMap[$format] ?? 'text/html'; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 806 |  |  |         $response->headers->set('Content-Type', $contentType); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 807 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 808 |  |  |         if (in_array($format, ['csv', 'tsv'])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 809 |  |  |             $filename = $this->getFilenameForRequest(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 810 |  |  |             $response->headers->set( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 811 |  |  |                 'Content-Disposition', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 812 |  |  |                 "attachment; filename=\"{$filename}.$format\"" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 813 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 814 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 815 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 816 |  |  |         return $response; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 817 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 818 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 819 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 820 |  |  |      * Returns given filename from the current Request, with problematic characters filtered out. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 821 |  |  |      * @return string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 822 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 823 |  |  |     private function getFilenameForRequest(): string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 824 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 825 |  |  |         $filename = trim($this->request->getPathInfo(), '/'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 826 |  |  |         return trim(preg_replace('/[-\/\\:;*?|<>%#"]+/', '-', $filename)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 827 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 828 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 829 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 830 |  |  |      * Return a JsonResponse object pre-supplied with the requested params. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 831 |  |  |      * @param array $data | 
            
                                                                                                            
                            
            
                                    
            
            
                | 832 |  |  |      * @return JsonResponse | 
            
                                                                                                            
                            
            
                                    
            
            
                | 833 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 834 |  |  |     public function getFormattedApiResponse(array $data): JsonResponse | 
            
                                                                                                            
                            
            
                                    
            
            
                | 835 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 836 |  |  |         $response = new JsonResponse(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 837 |  |  |         $response->setEncodingOptions(JSON_NUMERIC_CHECK); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 838 |  |  |         $response->setStatusCode(Response::HTTP_OK); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 839 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 840 |  |  |         // Normalize display of IP ranges (they are prefixed with 'ipr-' in the params). | 
            
                                                                                                            
                            
            
                                    
            
            
                | 841 |  |  |         if ($this->user && $this->user->isIpRange()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 842 |  |  |             $this->params['username'] = $this->user->getUsername(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 843 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 844 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 845 |  |  |         $elapsedTime = round( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 846 |  |  |             microtime(true) - $this->request->server->get('REQUEST_TIME_FLOAT'), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 847 |  |  |             3 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 848 |  |  |         ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 849 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 850 |  |  |         // Any pipe-separated values should be returned as an array. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 851 |  |  |         foreach ($this->params as $param => $value) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 852 |  |  |             if (is_string($value) && false !== strpos($value, '|')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 853 |  |  |                 $this->params[$param] = explode('|', $value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 854 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 855 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 856 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 857 |  |  |         $ret = array_merge($this->params, [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 858 |  |  |             // In some controllers, $this->params['project'] may be overridden with a Project object. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 859 |  |  |             'project' => $this->project->getDomain(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 860 |  |  |         ], $data, ['elapsed_time' => $elapsedTime]); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 861 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 862 |  |  |         // Merge in flash messages, putting them at the top. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 863 |  |  |         $flashes = $this->get('session')->getFlashBag()->peekAll(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 864 |  |  |         $ret = array_merge($flashes, $ret); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 865 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 866 |  |  |         // Flashes now can be cleared after merging into the response. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 867 |  |  |         $this->get('session')->getFlashBag()->clear(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 868 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 869 |  |  |         $response->setData($ret); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 870 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 871 |  |  |         return $response; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 872 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 873 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 874 |  |  |     /********* | 
            
                                                                                                            
                            
            
                                    
            
            
                | 875 |  |  |      * OTHER * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 876 |  |  |      *********/ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 877 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 878 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 879 |  |  |      * Record usage of an API endpoint. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 880 |  |  |      * @param string $endpoint | 
            
                                                                                                            
                            
            
                                    
            
            
                | 881 |  |  |      * @codeCoverageIgnore | 
            
                                                                                                            
                            
            
                                    
            
            
                | 882 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 883 |  |  |     public function recordApiUsage(string $endpoint): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 884 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 885 |  |  |         /** @var \Doctrine\DBAL\Connection $conn */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 886 |  |  |         $conn = $this->container->get('doctrine') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 887 |  |  |             ->getManager('default') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 888 |  |  |             ->getConnection(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 889 |  |  |         $date =  date('Y-m-d'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 890 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 891 |  |  |         // Increment count in timeline | 
            
                                                                                                            
                            
            
                                    
            
            
                | 892 |  |  |         $existsSql = "SELECT 1 FROM usage_api_timeline | 
            
                                                                                                            
                            
            
                                    
            
            
                | 893 |  |  |                       WHERE date = '$date' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 894 |  |  |                       AND endpoint = '$endpoint'"; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 895 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 896 |  |  |         try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 897 |  |  |             if (0 === count($conn->query($existsSql)->fetchAll())) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 898 |  |  |                 $createSql = "INSERT INTO usage_api_timeline | 
            
                                                                                                            
                            
            
                                    
            
            
                | 899 |  |  |                           VALUES(NULL, '$date', '$endpoint', 1)"; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 900 |  |  |                 $conn->query($createSql); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 901 |  |  |             } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 902 |  |  |                 $updateSql = "UPDATE usage_api_timeline | 
            
                                                                                                            
                            
            
                                    
            
            
                | 903 |  |  |                           SET count = count + 1 | 
            
                                                                                                            
                            
            
                                    
            
            
                | 904 |  |  |                           WHERE endpoint = '$endpoint' | 
            
                                                                                                            
                            
            
                                    
            
            
                | 905 |  |  |                           AND date = '$date'"; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 906 |  |  |                 $conn->query($updateSql); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 907 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 908 |  |  |         } catch (DBALException $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 909 |  |  |             // Do nothing. API response should still be returned rather than erroring out. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 910 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 911 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 912 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 913 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 914 |  |  |      * Add a flash message. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 915 |  |  |      * @param string $type | 
            
                                                                                                            
                            
            
                                    
            
            
                | 916 |  |  |      * @param string $key i18n key or raw message. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 917 |  |  |      * @param array $vars | 
            
                                                                                                            
                            
            
                                    
            
            
                | 918 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 919 |  |  |     public function addFlashMessage(string $type, string $key, array $vars = []): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 920 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 921 |  |  |         $this->addFlash( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 922 |  |  |             $type, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 923 |  |  |             $this->i18n->msgExists($key, $vars) ? $this->i18n->msg($key, $vars) : $key | 
            
                                                                                                            
                            
            
                                    
            
            
                | 924 |  |  |         ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 925 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 926 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 927 |  |  |  |