loadBalancer = $loadBalancer; $this->permissionManager = $permissionManager; $this->userFactory = $userFactory; } /** * Do a prefix search of user names and return a list of matching user names. * * @param string|UserIdentity $audience Either AUDIENCE_PUBLIC or a user to show the search for * @param string $search * @param int $limit * @param int $offset How many results to offset from the beginning * @return string[] * @throws InvalidArgumentException if $audience is invalid */ public function search( $audience, string $search, int $limit, int $offset = 0 ) : array { if ( $audience !== self::AUDIENCE_PUBLIC && !( $audience instanceof UserIdentity ) ) { throw new InvalidArgumentException( '$audience must be AUDIENCE_PUBLIC or a UserIdentity' ); } // TODO this was kept when switching to a service, but it should probably // use UserNameUtils::getCanonical( $search, UserNameUtils::RIGOR_VALID ) and // use an empty string if that is false, or the returned string, instead of // taking the time to construct a user object. $user = $this->userFactory->newFromName( $search ); $prefix = $user ? $user->getName() : ''; $dbr = $this->loadBalancer->getConnectionRef( DB_REPLICA ); $tables = [ 'user' ]; $conds = [ 'user_name ' . $dbr->buildLike( $prefix, $dbr->anyString() ) ]; $joinConds = []; // Filter out hidden user names if ( $audience === self::AUDIENCE_PUBLIC || !$this->permissionManager->userHasRight( $audience, 'hideuser' ) ) { $tables[] = 'ipblocks'; $conds['ipb_deleted'] = [ 0, null ]; $joinConds['ipblocks'] = [ 'LEFT JOIN', 'user_id=ipb_user' ]; } $res = $dbr->selectFieldValues( $tables, 'user_name', $conds, __METHOD__, [ 'LIMIT' => $limit, 'ORDER BY' => 'user_name', 'OFFSET' => $offset ], $joinConds ); return $res; } }