Skip to content

Commit

Permalink
[11.13] Add support for Advanced Search API (#783)
Browse files Browse the repository at this point in the history
* [11.8] Added search API

* Fixed lint issues

* Fixed last issue with Search API

* remove pagination parameters

https://github.com/GitLabPHP/Client/pull/696/files#r857165665

* mark required properties

* add state parameter

* add newer scopes

* add search endpoint to groups and projects

* add missing namespaces

* fix code style

---------

Co-authored-by: Adrian David Castro Tenemaya <[email protected]>
  • Loading branch information
macbookandrew and IAL32 authored Dec 3, 2023
1 parent b3244ef commit 89eef50
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 0 deletions.
53 changes: 53 additions & 0 deletions src/Api/Groups.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

namespace Gitlab\Api;

use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
use Symfony\Component\OptionsResolver\Options;
use Symfony\Component\OptionsResolver\OptionsResolver;

Expand Down Expand Up @@ -979,4 +981,55 @@ public function deleteDeployToken($group_id, int $token_id)
{
return $this->delete('groups/'.self::encodePath($group_id).'/deploy_tokens/'.self::encodePath($token_id));
}

/**
* @param int|string $id
* @param array $parameters {
*
* @var string $scope The scope to search in
* @var string $search The search query
* @var string $state Filter by state. Issues and merge requests are supported; it is ignored for other scopes.
* @var bool $confidential Filter by confidentiality. Issues scope is supported; it is ignored for other scopes.
* @var string $order_by Allowed values are created_at only. If this is not set, the results are either sorted by created_at in descending order for basic search, or by the most relevant documents when using advanced search.
* @var string $sort Return projects sorted in asc or desc order (default is desc)
* }
*
* @throws UndefinedOptionsException If an option name is undefined
* @throws InvalidOptionsException If an option doesn't fulfill the
* specified validation rules
*
* @return mixed
*/
public function search($id, array $parameters = [])
{
$resolver = $this->createOptionsResolver();
$booleanNormalizer = function (Options $resolver, $value): string {
return $value ? 'true' : 'false';
};
$resolver->setDefined('confidential')
->setAllowedTypes('confidential', 'bool')
->setNormalizer('confidential', $booleanNormalizer);
$scope = [
'issues',
'merge_requests',
'milestones',
'projects',
'users',
'blobs',
'commits',
'notes',
'wiki_blobs',
];
$resolver->setRequired('scope')
->setAllowedValues('scope', $scope);
$resolver->setRequired('search');
$resolver->setDefined('order_by')
->setAllowedValues('order_by', ['created_at']);
$resolver->setDefined('sort')
->setAllowedValues('sort', ['asc', 'desc']);
$resolver->setDefined('state')
->setAllowedValues('state', ['opened', 'closed']);

return $this->get('groups/'.self::encodePath($id).'/search', $resolver->resolve($parameters));
}
}
53 changes: 53 additions & 0 deletions src/Api/Projects.php
Original file line number Diff line number Diff line change
Expand Up @@ -1781,4 +1781,57 @@ public function deleteProtectedTag($project_id, string $tag_name)
{
return $this->delete($this->getProjectPath($project_id, 'protected_tags/'.self::encodePath($tag_name)));
}

/**
* @param int|string $id
* @param array $parameters {
*
* @var string $scope The scope to search in
* @var string $search The search query
* @var string $state Filter by state. Issues and merge requests are supported; it is ignored for other scopes.
* @var string $ref The name of a repository branch or tag to search on. The project’s default branch is used by default. Applicable only for scopes blobs, commits, and wiki_blobs.
* @var bool $confidential Filter by confidentiality. Issues scope is supported; it is ignored for other scopes.
* @var string $order_by Allowed values are created_at only. If this is not set, the results are either sorted by created_at in descending order for basic search, or by the most relevant documents when using advanced search.
* @var string $sort Return projects sorted in asc or desc order (default is desc)
* }
*
* @throws UndefinedOptionsException If an option name is undefined
* @throws InvalidOptionsException If an option doesn't fulfill the
* specified validation rules
*
* @return mixed
*/
public function search($id, array $parameters = [])
{
$resolver = $this->createOptionsResolver();
$booleanNormalizer = function (Options $resolver, $value): string {
return $value ? 'true' : 'false';
};
$resolver->setDefined('confidential')
->setAllowedTypes('confidential', 'bool')
->setNormalizer('confidential', $booleanNormalizer);
$scope = [
'blobs',
'commits',
'issues',
'merge_requests',
'milestones',
'notes',
'users',
'wiki_blobs',
];
$resolver->setRequired('scope')
->setAllowedValues('scope', $scope);
$resolver->setRequired('search');
$resolver->setDefined('ref')
->setAllowedTypes('ref', 'string');
$resolver->setDefined('order_by')
->setAllowedValues('order_by', ['created_at']);
$resolver->setDefined('sort')
->setAllowedValues('sort', ['asc', 'desc']);
$resolver->setDefined('state')
->setAllowedValues('state', ['opened', 'closed']);

return $this->get('projects/'.self::encodePath($id).'/search', $resolver->resolve($parameters));
}
}
73 changes: 73 additions & 0 deletions src/Api/Search.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Gitlab API library.
*
* (c) Matt Humphrey <[email protected]>
* (c) Graham Campbell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Gitlab\Api;

use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException;
use Symfony\Component\OptionsResolver\Options;

class Search extends AbstractApi
{
/**
* @param array $parameters {
*
* @var string $scope The scope to search in
* @var string $search The search query
* @var string $state Filter by state. Issues and merge requests are supported; it is ignored for other scopes.
* @var bool $confidential Filter by confidentiality. Issues scope is supported; it is ignored for other scopes.
* @var string $order_by Allowed values are created_at only. If this is not set, the results are either sorted by created_at in descending order for basic search, or by the most relevant documents when using advanced search.
* @var string $sort Return projects sorted in asc or desc order (default is desc)
* }
*
* @throws UndefinedOptionsException If an option name is undefined
* @throws InvalidOptionsException If an option doesn't fulfill the
* specified validation rules
*
* @return mixed
*/
public function all(array $parameters = [])
{
$resolver = $this->createOptionsResolver();
$booleanNormalizer = function (Options $resolver, $value): string {
return $value ? 'true' : 'false';
};
$resolver->setDefined('confidential')
->setAllowedTypes('confidential', 'bool')
->setNormalizer('confidential', $booleanNormalizer);
$scope = [
'projects',
'issues',
'merge_requests',
'milestones',
'snippet_titles',
'wiki_blobs',
'commits',
'blobs',
'notes',
'users',
];
$resolver->setRequired('scope')
->setAllowedValues('scope', $scope);
$resolver->setRequired('search');
$resolver->setDefined('order_by')
->setAllowedValues('order_by', ['created_at']);
$resolver->setDefined('sort')
->setAllowedValues('sort', ['asc', 'desc']);
$resolver->setDefined('state')
->setAllowedValues('state', ['opened', 'closed']);

return $this->get('search', $resolver->resolve($parameters));
}
}
9 changes: 9 additions & 0 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
use Gitlab\Api\ResourceStateEvents;
use Gitlab\Api\ResourceWeightEvents;
use Gitlab\Api\Schedules;
use Gitlab\Api\Search;
use Gitlab\Api\Snippets;
use Gitlab\Api\SystemHooks;
use Gitlab\Api\Tags;
Expand Down Expand Up @@ -351,6 +352,14 @@ public function repositoryFiles(): RepositoryFiles
return new RepositoryFiles($this);
}

/**
* @return Search
*/
public function search(): Search
{
return new Search($this);
}

/**
* @return Schedules
*/
Expand Down
32 changes: 32 additions & 0 deletions tests/Api/GroupsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -940,4 +940,36 @@ public function shouldDeleteDeployToken(): void

$this->assertEquals($expectedBool, $api->deleteDeployToken(1, 2));
}

/**
* @test
*/
public function shouldSearchGroups(): void
{
$expectedArray = [
['id' => 6, 'name' => 'Project 6 bla'],
['id' => 7, 'name' => 'Project 7 bla'],
['id' => 8, 'name' => 'Project 8 bla'],
];

$api = $this->getApiMock();
$api->expects($this->once())
->method('get')
->with('groups/123/search', [
'scope' => 'projects',
'confidential' => 'false',
'search' => 'bla',
'order_by' => 'created_at',
'sort' => 'desc',
])
->will($this->returnValue($expectedArray));

$this->assertEquals($expectedArray, $api->search(123, [
'scope' => 'projects',
'confidential' => false,
'search' => 'bla',
'order_by' => 'created_at',
'sort' => 'desc',
]));
}
}
32 changes: 32 additions & 0 deletions tests/Api/ProjectsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3017,4 +3017,36 @@ protected function getApiClass()
{
return Projects::class;
}

/**
* @test
*/
public function shouldSearchGroups(): void
{
$expectedArray = [
['id' => 6, 'title' => 'Issue 6 bla'],
['id' => 7, 'title' => 'Issue 7 bla'],
['id' => 8, 'title' => 'Issue 8 bla'],
];

$api = $this->getApiMock();
$api->expects($this->once())
->method('get')
->with('projects/123/search', [
'scope' => 'issues',
'confidential' => 'false',
'search' => 'bla',
'order_by' => 'created_at',
'sort' => 'desc',
])
->will($this->returnValue($expectedArray));

$this->assertEquals($expectedArray, $api->search(123, [
'scope' => 'issues',
'confidential' => false,
'search' => 'bla',
'order_by' => 'created_at',
'sort' => 'desc',
]));
}
}
57 changes: 57 additions & 0 deletions tests/Api/SearchTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

/*
* This file is part of the Gitlab API library.
*
* (c) Matt Humphrey <[email protected]>
* (c) Graham Campbell <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Gitlab\Tests\Api;

use Gitlab\Api\Search;

class SearchTest extends TestCase
{
/**
* @test
*/
public function shouldGetAll(): void
{
$expectedArray = [
['id' => 6, 'name' => 'Project 6 bla'],
['id' => 7, 'name' => 'Project 7 bla'],
['id' => 8, 'name' => 'Project 8 bla'],
];

$api = $this->getApiMock();
$api->expects($this->once())
->method('get')
->with('search', [
'scope' => 'projects',
'confidential' => 'false',
'search' => 'bla',
'order_by' => 'created_at',
'sort' => 'desc',
])
->will($this->returnValue($expectedArray));

$this->assertEquals($expectedArray, $api->all([
'scope' => 'projects',
'confidential' => false,
'search' => 'bla',
'order_by' => 'created_at',
'sort' => 'desc',
]));
}

protected function getApiClass()
{
return Search::class;
}
}

0 comments on commit 89eef50

Please sign in to comment.