Skip to content

Commit 655a667

Browse files
authored
Merge pull request #62 from ensi-platform/v7-ecs-827
ECS-827 Add highlight
2 parents 3bfc38d + b17d623 commit 655a667

File tree

11 files changed

+241
-2
lines changed

11 files changed

+241
-2
lines changed

src/Contracts/DSL.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuery\Contracts;
4+
5+
use stdClass;
6+
7+
class DSL
8+
{
9+
public static function filter(array $dsl): array|stdClass
10+
{
11+
return array_filter($dsl, fn (mixed $item) => !is_null($item)) ?: new stdClass;
12+
}
13+
}

src/Contracts/DSLAware.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace Ensi\LaravelElasticQuery\Contracts;
44

5+
use stdClass;
6+
57
interface DSLAware
68
{
7-
public function toDSL(): array;
9+
public function toDSL(): array|stdClass;
810
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuery\Contracts;
4+
5+
use Ensi\LaravelElasticQuery\Search\Highlight\Highlight;
6+
7+
interface HighlightingQuery extends BoolQuery
8+
{
9+
public function highlight(Highlight $highlight): static;
10+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuery\Search\Enums;
4+
5+
class BoundaryScanner
6+
{
7+
public const CHARS = 'chars';
8+
public const SENTENCE = 'sentence';
9+
public const WORD = 'word';
10+
11+
public static function cases(): array
12+
{
13+
return [
14+
self::CHARS,
15+
self::SENTENCE,
16+
self::WORD,
17+
];
18+
}
19+
}

src/Search/Enums/Encoder.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuery\Search\Enums;
4+
5+
class Encoder
6+
{
7+
public const DEFAULT = 'default';
8+
public const HTML = 'html';
9+
10+
public static function cases(): array
11+
{
12+
return [
13+
self::DEFAULT,
14+
self::HTML,
15+
];
16+
}
17+
}

src/Search/Enums/Fragmenter.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuery\Search\Enums;
4+
5+
class Fragmenter
6+
{
7+
public const SIMPLE = 'simple';
8+
public const SPAN = 'span';
9+
10+
public static function cases(): array
11+
{
12+
return [
13+
self::SIMPLE,
14+
self::SPAN,
15+
];
16+
}
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuery\Search\Enums;
4+
5+
class HighlightOrder
6+
{
7+
public const NONE = 'none';
8+
public const SCORE = 'score';
9+
10+
public static function cases(): array
11+
{
12+
return [
13+
self::NONE,
14+
self::SCORE,
15+
];
16+
}
17+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuery\Search\Enums;
4+
5+
class HighlightTagsSchema
6+
{
7+
public const STYLED = 'styled';
8+
9+
public static function cases(): array
10+
{
11+
return [
12+
self::STYLED,
13+
];
14+
}
15+
}

src/Search/Enums/HighlightType.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuery\Search\Enums;
4+
5+
class HighlightType
6+
{
7+
public const UNIFIED = 'unified';
8+
public const PLAIN = 'plain';
9+
public const FVH = 'fvh';
10+
11+
public static function cases(): array
12+
{
13+
return [
14+
self::UNIFIED,
15+
self::PLAIN,
16+
self::FVH,
17+
];
18+
}
19+
}

src/Search/Highlight/Highlight.php

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
3+
namespace Ensi\LaravelElasticQuery\Search\Highlight;
4+
5+
use Ensi\LaravelElasticQuery\Contracts\DSL;
6+
use Ensi\LaravelElasticQuery\Contracts\DSLAware;
7+
use Ensi\LaravelElasticQuery\Filtering\BoolQueryBuilder;
8+
use Ensi\LaravelElasticQuery\Search\Enums\BoundaryScanner;
9+
use Ensi\LaravelElasticQuery\Search\Enums\Encoder;
10+
use Ensi\LaravelElasticQuery\Search\Enums\Fragmenter;
11+
use Ensi\LaravelElasticQuery\Search\Enums\HighlightOrder;
12+
use Ensi\LaravelElasticQuery\Search\Enums\HighlightTagsSchema;
13+
use Ensi\LaravelElasticQuery\Search\Enums\HighlightType;
14+
use stdClass;
15+
use Webmozart\Assert\Assert;
16+
17+
class Highlight implements DSLAware
18+
{
19+
private array $fields = [];
20+
21+
public function __construct(
22+
array $fields = [],
23+
private ?string $boundaryChars = null,
24+
private ?int $boundaryMaxScan = null,
25+
private ?string $boundaryScanner = null,
26+
private ?string $boundaryScannerLocale = null,
27+
private ?string $encoder = null,
28+
private ?bool $forceSource = null,
29+
private ?string $fragmenter = null,
30+
private ?int $fragmentOffset = null,
31+
private ?int $fragmentSize = null,
32+
private ?BoolQueryBuilder $highlightQuery = null,
33+
private ?array $matchedFields = null,
34+
private ?int $noMatchSize = null,
35+
private ?int $numberOfFragments = null,
36+
private ?string $order = null,
37+
private ?int $phraseLimit = null,
38+
private ?string $preTags = null,
39+
private ?string $postTags = null,
40+
private ?bool $requireFieldMatch = null,
41+
private ?int $maxAnalyzedOffset = null,
42+
private ?string $tagsSchema = null,
43+
private ?string $type = null,
44+
) {
45+
Assert::nullOrInArray($this->boundaryScanner, BoundaryScanner::cases());
46+
Assert::nullOrInArray($this->encoder, Encoder::cases());
47+
Assert::nullOrInArray($this->fragmenter, Fragmenter::cases());
48+
Assert::nullOrInArray($this->order, HighlightOrder::cases());
49+
Assert::nullOrInArray($this->tagsSchema, HighlightTagsSchema::cases());
50+
Assert::nullOrInArray($this->type, HighlightType::cases());
51+
52+
foreach ($fields as $fieldKey => $fieldValue) {
53+
if (is_string($fieldValue)) {
54+
$this->fields[$fieldValue] = new static();
55+
} else {
56+
$this->fields[$fieldKey] = $fieldValue;
57+
}
58+
}
59+
Assert::allIsInstanceOf($this->fields, static::class);
60+
}
61+
62+
public function toDSL(): array|stdClass
63+
{
64+
return DSL::filter(array_filter([
65+
'boundary_chars' => $this->boundaryChars,
66+
'boundary_max_scan' => $this->boundaryMaxScan,
67+
'boundary_scanner' => $this->boundaryScanner,
68+
'boundary_scanner_locale' => $this->boundaryScannerLocale,
69+
70+
'encoder' => $this->encoder,
71+
72+
'fields' => array_map(fn (Highlight $field) => $field->toDSL(), $this->fields) ?: null,
73+
74+
'force_source' => $this->forceSource,
75+
76+
'fragmenter' => $this->fragmenter,
77+
'fragment_offset' => $this->fragmentOffset,
78+
'fragment_size' => $this->fragmentSize,
79+
80+
'highlight_query' => $this->highlightQuery?->toDSL(),
81+
'matched_fields' => $this->matchedFields,
82+
'no_match_size' => $this->noMatchSize,
83+
'number_of_fragments' => $this->numberOfFragments,
84+
'order' => $this->order,
85+
'phrase_limit' => $this->phraseLimit,
86+
87+
'pre_tags' => $this->preTags,
88+
'post_tags' => $this->postTags,
89+
90+
'require_field_match' => $this->requireFieldMatch,
91+
'max_analyzed_offset' => $this->maxAnalyzedOffset,
92+
'tags_schema' => $this->tagsSchema,
93+
'type' => $this->type,
94+
]));
95+
}
96+
}

0 commit comments

Comments
 (0)