Skip to content

Commit 1407247

Browse files
String function improvements and additions
TRIM's second value is optional now. It also accepts a string with characters to remove at the beginnen and the end, instead of just the type integer. Added LTRIM support Added RTRIM support Added FIND_FIRST support Added FIND_LAST support Moved CI QA scripts to separate shell script
1 parent e955b21 commit 1407247

File tree

6 files changed

+260
-38
lines changed

6 files changed

+260
-38
lines changed

.github/workflows/ci.yml

+5-19
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ on: [workflow_dispatch, push, pull_request]
44

55
jobs:
66
run:
7-
runs-on: ubuntu-18.04
7+
runs-on: ubuntu-latest
88
strategy:
99
matrix:
1010
php-versions: [8.0, 8.1]
@@ -25,22 +25,8 @@ jobs:
2525
- name: Install dependencies
2626
run: composer install --prefer-dist --no-progress --no-suggest
2727

28-
- name: PHP Code Sniffer
28+
- name: Run all QA tests
2929
if: ${{ always() }}
30-
run: vendor/bin/phpcs
31-
32-
- name: PHP Mess Detector
33-
if: ${{ always() }}
34-
run: vendor/bin/phpmd src/ text phpmd-ruleset.xml
35-
36-
- name: PHP Stan
37-
if: ${{ always() }}
38-
run: vendor/bin/phpstan analyse -c phpstan.neon
39-
40-
- name: Psalm
41-
if: ${{ always() }}
42-
run: vendor/bin/psalm --no-cache
43-
44-
- name: PHP Unit tests
45-
if: ${{ always() }}
46-
run: vendor/bin/phpunit
30+
run: |
31+
chmod +x "${GITHUB_WORKSPACE}/bin/qa.sh"
32+
"${GITHUB_WORKSPACE}/bin/qa.sh"

bin/qa.sh

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
echo "Fix coding style"
3+
./vendor/bin/phpcbf
4+
5+
echo "Check for remaining coding style errors"
6+
./vendor/bin/phpcs -p --ignore=tests
7+
8+
echo "Run PHPMD"
9+
./vendor/bin/phpmd src/ text phpmd-ruleset.xml
10+
11+
echo "Run PHPStan"
12+
./vendor/bin/phpstan analyse -c phpstan.neon
13+
14+
echo "Run Psalm"
15+
./vendor/bin/psalm --no-cache
16+
17+
echo "Run PHPUnit"
18+
./vendor/bin/phpunit

docs/api/functions.md

+21-19
Original file line numberDiff line numberDiff line change
@@ -135,25 +135,27 @@ The following functions are directly supported in FluentAql.
135135

136136

137137
### String functions
138-
| Description | AQL Function |
139-
|:---------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------|
140-
| concat(...$arguments) | [CONCAT(value1, value2, ... valueN)](https://www.arangodb.com/docs/stable/aql/functions-string.html#concat) |
141-
| concatSeparator($separator, $values) | [CONCAT_SEPARATOR(separator, value1, value2, ... valueN)](https://www.arangodb.com/docs/stable/aql/functions-string.html#concat_separator) |
142-
| levenshteinDistance($value1, $value2) | [LEVENSHTEIN_DISTANCE(value1, value2)](https://www.arangodb.com/docs/stable/aql/functions-string.html#levenshtein_distance) |
143-
| lower($value) | [LOWER(value)](https://www.arangodb.com/docs/stable/aql/functions-string.html#lower) |
144-
| ltrim($value, $char) | [LTRIM(value, char)](https://www.arangodb.com/docs/stable/aql/functions-string.html#ltrim) |
145-
| regexMatches($text, $regex, $caseInsensitive) | [REGEX_MATCHES(text, regex, caseInsensitive)](https://www.arangodb.com/docs/stable/aql/functions-string.html#regex_matches) |
146-
| regexReplace($text, $regex, $replacement, $caseInsensitive) | [REGEX_REPLACE(text, search, replacement, caseInsensitive)](https://www.arangodb.com/docs/stable/aql/functions-string.html#regex_replace) |
147-
| regexSplit($text, $splitExpression, $caseInsensitive, $limit) | [REGEX_SPLIT(text, splitExpression, caseInsensitive, limit)](https://www.arangodb.com/docs/stable/aql/functions-string.html#regex_split) |
148-
| regexTest($text, $search, $caseInsensitive) | [REGEX_TEST(text, search, caseInsensitive)](https://www.arangodb.com/docs/stable/aql/functions-string.html#regex_test) |
149-
| rtrim($value, $char) | [RTRIM(value, char)](https://www.arangodb.com/docs/stable/aql/functions-string.html#rtrim) |
150-
| split($value, $separator, $limit) | [SPLIT(value, separator, limit)](https://www.arangodb.com/docs/stable/aql/functions-string.html#split) |
151-
| substitute($text, $search, $replace, $limit) | [SUBSTITUTE(value, search, replace, limit)](https://www.arangodb.com/docs/stable/aql/functions-string.html#substitute) |
152-
| substring($value, $offset, $length) | [SUBSTRING(value, offset, length)](https://www.arangodb.com/docs/stable/aql/functions-string.html#substitute) |
153-
| tokens($input, $analyzer) | [TOKENS(input, analyzer)](https://www.arangodb.com/docs/stable/aql/functions-string.html#tokens) |
154-
| trim($value, $type) | [TRIM(value, type)](https://www.arangodb.com/docs/stable/aql/functions-string.html#trim) |
155-
| upper($value) | [UPPER(value)](https://www.arangodb.com/docs/stable/aql/functions-string.html#upper) |
156-
| uuid() | [UUID()](https://www.arangodb.com/docs/stable/aql/functions-string.html#uuid) |
138+
| Description | AQL Function |
139+
|:--------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------|
140+
| concat(...$arguments) | [CONCAT(value1, value2, ... valueN)](https://www.arangodb.com/docs/stable/aql/functions-string.html#concat) |
141+
| concatSeparator($separator, $values) | [CONCAT_SEPARATOR(separator, value1, value2, ... valueN)](https://www.arangodb.com/docs/stable/aql/functions-string.html#concat_separator) |
142+
| findFirst($text, $search, $start, $end) | [FIND_FIRST(text, search, start, end)](https://www.arangodb.com/docs/stable/aql/functions-string.html#find_first) |
143+
| findLast($text, $search, $start, $end) | [FIND_Last(text, search, start, end)](https://www.arangodb.com/docs/stable/aql/functions-string.html#find_Last) |
144+
| levenshteinDistance($value1, $value2) | [LEVENSHTEIN_DISTANCE(value1, value2)](https://www.arangodb.com/docs/stable/aql/functions-string.html#levenshtein_distance) |
145+
| lower($value) | [LOWER(value)](https://www.arangodb.com/docs/stable/aql/functions-string.html#lower) |
146+
| ltrim($value, $char) | [LTRIM(value, char)](https://www.arangodb.com/docs/stable/aql/functions-string.html#ltrim) |
147+
| regexMatches($text, $regex, $caseInsensitive) | [REGEX_MATCHES(text, regex, caseInsensitive)](https://www.arangodb.com/docs/stable/aql/functions-string.html#regex_matches) |
148+
| regexReplace($text, $regex, $replacement, $caseInsensitive) | [REGEX_REPLACE(text, search, replacement, caseInsensitive)](https://www.arangodb.com/docs/stable/aql/functions-string.html#regex_replace) |
149+
| regexSplit($text, $splitExpression, $caseInsensitive, $limit) | [REGEX_SPLIT(text, splitExpression, caseInsensitive, limit)](https://www.arangodb.com/docs/stable/aql/functions-string.html#regex_split) |
150+
| regexTest($text, $search, $caseInsensitive) | [REGEX_TEST(text, search, caseInsensitive)](https://www.arangodb.com/docs/stable/aql/functions-string.html#regex_test) |
151+
| rtrim($value, $char) | [RTRIM(value, char)](https://www.arangodb.com/docs/stable/aql/functions-string.html#rtrim) |
152+
| split($value, $separator, $limit) | [SPLIT(value, separator, limit)](https://www.arangodb.com/docs/stable/aql/functions-string.html#split) |
153+
| substitute($text, $search, $replace, $limit) | [SUBSTITUTE(value, search, replace, limit)](https://www.arangodb.com/docs/stable/aql/functions-string.html#substitute) |
154+
| substring($value, $offset, $length) | [SUBSTRING(value, offset, length)](https://www.arangodb.com/docs/stable/aql/functions-string.html#substitute) |
155+
| tokens($input, $analyzer) | [TOKENS(input, analyzer)](https://www.arangodb.com/docs/stable/aql/functions-string.html#tokens) |
156+
| trim($value, $type) | [TRIM(value, type)](https://www.arangodb.com/docs/stable/aql/functions-string.html#trim) |
157+
| upper($value) | [UPPER(value)](https://www.arangodb.com/docs/stable/aql/functions-string.html#upper) |
158+
| uuid() | [UUID()](https://www.arangodb.com/docs/stable/aql/functions-string.html#uuid) |
157159

158160

159161
### Type functions

src/AQL/HasStringFunctions.php

+62
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,57 @@ public function contains(
5959
return new FunctionExpression('CONTAINS', [$text, $search, $returnIndex]);
6060
}
6161

62+
/**
63+
* Return the position of the first occurrence of the string search inside the string text. Positions start at 0.
64+
*
65+
* @link https://www.arangodb.com/docs/stable/aql/functions-string.html#find_first
66+
*/
67+
public function findFirst(
68+
string|object $text,
69+
string|object $search,
70+
int|object $start = null,
71+
int|object $end = null
72+
): FunctionExpression {
73+
$arguments = [
74+
'text' => $text,
75+
'search' => $search,
76+
];
77+
if (isset($start)) {
78+
$arguments['start'] = $start;
79+
}
80+
if (isset($end)) {
81+
$arguments['end'] = $end;
82+
}
83+
84+
return new FunctionExpression('FIND_FIRST', $arguments);
85+
}
86+
87+
88+
/**
89+
* Return the position of the last occurrence of the string search inside the string text. Positions start at 0.
90+
*
91+
* @link https://www.arangodb.com/docs/stable/aql/functions-string.html#find_last
92+
*/
93+
public function findLast(
94+
string|object $text,
95+
string|object $search,
96+
int|object $start = null,
97+
int|object $end = null
98+
): FunctionExpression {
99+
$arguments = [
100+
'text' => $text,
101+
'search' => $search,
102+
];
103+
if (isset($start)) {
104+
$arguments['start'] = $start;
105+
}
106+
if (isset($end)) {
107+
$arguments['end'] = $end;
108+
}
109+
110+
return new FunctionExpression('FIND_LAST', $arguments);
111+
}
112+
62113
/**
63114
* Calculate the Damerau-Levenshtein distance between two strings.
64115
*
@@ -187,6 +238,17 @@ public function rtrim(
187238
return new FunctionExpression('RTRIM', $arguments);
188239
}
189240

241+
/**
242+
* Return the soundex fingerprint of value.
243+
*
244+
* @link https://www.arangodb.com/docs/stable/aql/functions-string.html#soundex
245+
*/
246+
public function soundex(
247+
string|object $value,
248+
): FunctionExpression {
249+
return new FunctionExpression('SOUNDEX', [$value]);
250+
}
251+
190252
/**
191253
* Split the given string text into a list of strings, using the separator.
192254
*

src/Traits/NormalizesStringFunctions.php

+59
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,60 @@ protected function normalizeContains(QueryBuilder $queryBuilder): void
4343
);
4444
}
4545

46+
protected function normalizeFindFirst(QueryBuilder $queryBuilder): void
47+
{
48+
$this->parameters['text'] = $queryBuilder->normalizeArgument(
49+
$this->parameters['text'],
50+
['Query', 'Reference', 'Bind']
51+
);
52+
53+
$this->parameters['search'] = $queryBuilder->normalizeArgument(
54+
$this->parameters['search'],
55+
['Query', 'Reference', 'Bind']
56+
);
57+
58+
if (isset($this->parameters['start'])) {
59+
$this->parameters['start'] = $queryBuilder->normalizeArgument(
60+
$this->parameters['start'],
61+
['Number', 'Query', 'Reference', 'Bind']
62+
);
63+
}
64+
65+
if (isset($this->parameters['end'])) {
66+
$this->parameters['end'] = $queryBuilder->normalizeArgument(
67+
$this->parameters['end'],
68+
['Number', 'Query', 'Reference', 'Bind']
69+
);
70+
}
71+
}
72+
73+
protected function normalizeFindLast(QueryBuilder $queryBuilder): void
74+
{
75+
$this->parameters['text'] = $queryBuilder->normalizeArgument(
76+
$this->parameters['text'],
77+
['Query', 'Reference', 'Bind']
78+
);
79+
80+
$this->parameters['search'] = $queryBuilder->normalizeArgument(
81+
$this->parameters['search'],
82+
['Query', 'Reference', 'Bind']
83+
);
84+
85+
if (isset($this->parameters['start'])) {
86+
$this->parameters['start'] = $queryBuilder->normalizeArgument(
87+
$this->parameters['start'],
88+
['Number', 'Query', 'Reference', 'Bind']
89+
);
90+
}
91+
92+
if (isset($this->parameters['end'])) {
93+
$this->parameters['end'] = $queryBuilder->normalizeArgument(
94+
$this->parameters['end'],
95+
['Number', 'Query', 'Reference', 'Bind']
96+
);
97+
}
98+
}
99+
46100
protected function normalizeLevenshteinDistance(QueryBuilder $queryBuilder): void
47101
{
48102
$this->normalizeStrings($queryBuilder);
@@ -163,6 +217,11 @@ protected function normalizeRtrim(QueryBuilder $queryBuilder): void
163217
);
164218
}
165219

220+
protected function normalizeSoundex(QueryBuilder $queryBuilder): void
221+
{
222+
$this->normalizeStrings($queryBuilder);
223+
}
224+
166225
protected function normalizeSplit(QueryBuilder $queryBuilder): void
167226
{
168227
$this->parameters['value'] = $queryBuilder->normalizeArgument(

tests/Unit/AQL/StringFunctionsTest.php

+95
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,90 @@ public function testContains()
5151
);
5252
}
5353

54+
public function testContainsReturnsIndex()
55+
{
56+
$qb = new QueryBuilder();
57+
$qb->return($qb->contains('foobarbaz', 'bar', true));
58+
self::assertEquals(
59+
'RETURN CONTAINS(@'
60+
. $qb->getQueryId() . '_1, @'
61+
. $qb->getQueryId() . '_2, true)',
62+
$qb->get()->query
63+
);
64+
}
65+
66+
public function testFindFirst()
67+
{
68+
$qb = new QueryBuilder();
69+
$qb->return($qb->findFirst('foobarbaz', 'bar'));
70+
self::assertEquals(
71+
'RETURN FIND_FIRST(@'
72+
. $qb->getQueryId() . '_1, @'
73+
. $qb->getQueryId() . '_2)',
74+
$qb->get()->query
75+
);
76+
}
77+
78+
public function testFindFirstWithStart()
79+
{
80+
$qb = new QueryBuilder();
81+
$qb->return($qb->findFirst('foobarbaz', 'bar', 3));
82+
self::assertEquals(
83+
'RETURN FIND_FIRST(@'
84+
. $qb->getQueryId() . '_1, @'
85+
. $qb->getQueryId() . '_2, 3)',
86+
$qb->get()->query
87+
);
88+
}
89+
90+
public function testFindFirstWithStartAndEnd()
91+
{
92+
$qb = new QueryBuilder();
93+
$qb->return($qb->findFirst('foobarbaz', 'bar', 3, 12));
94+
self::assertEquals(
95+
'RETURN FIND_FIRST(@'
96+
. $qb->getQueryId() . '_1, @'
97+
. $qb->getQueryId() . '_2, 3, 12)',
98+
$qb->get()->query
99+
);
100+
}
101+
102+
public function testFindLast()
103+
{
104+
$qb = new QueryBuilder();
105+
$qb->return($qb->findLast('foobarbaz', 'bar'));
106+
self::assertEquals(
107+
'RETURN FIND_LAST(@'
108+
. $qb->getQueryId() . '_1, @'
109+
. $qb->getQueryId() . '_2)',
110+
$qb->get()->query
111+
);
112+
}
113+
114+
public function testFindLastWithStart()
115+
{
116+
$qb = new QueryBuilder();
117+
$qb->return($qb->findLast('foobarbaz', 'bar', 3));
118+
self::assertEquals(
119+
'RETURN FIND_LAST(@'
120+
. $qb->getQueryId() . '_1, @'
121+
. $qb->getQueryId() . '_2, 3)',
122+
$qb->get()->query
123+
);
124+
}
125+
126+
public function testFindLastWithStartAndEnd()
127+
{
128+
$qb = new QueryBuilder();
129+
$qb->return($qb->findLast('foobarbaz', 'bar', 3, 12));
130+
self::assertEquals(
131+
'RETURN FIND_LAST(@'
132+
. $qb->getQueryId() . '_1, @'
133+
. $qb->getQueryId() . '_2, 3, 12)',
134+
$qb->get()->query
135+
);
136+
}
137+
54138
public function testContainsReturnIndex()
55139
{
56140
$qb = new QueryBuilder();
@@ -170,6 +254,17 @@ public function testRightTrimWithChar()
170254
);
171255
}
172256

257+
public function testSoundex()
258+
{
259+
$qb = new QueryBuilder();
260+
$qb->return($qb->soundex('foobarbaz'));
261+
self::assertEquals(
262+
'RETURN SOUNDEX(@'
263+
. $qb->getQueryId() . '_1)',
264+
$qb->get()->query
265+
);
266+
}
267+
173268
public function testSplit()
174269
{
175270
$qb = new QueryBuilder();

0 commit comments

Comments
 (0)