Skip to content

Commit 8088588

Browse files
committed
improve tag syncing to include minor versions to plugins properly display if they support only certain minor versions of cakephp
1 parent 70964fb commit 8088588

File tree

4 files changed

+115
-22
lines changed

4 files changed

+115
-22
lines changed

src/Command/SyncPackagesCommand.php

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
use Cake\Console\CommandFactoryInterface;
99
use Cake\Console\ConsoleIo;
1010
use Cake\Log\Log;
11+
use Composer\Semver\Intervals;
1112
use Composer\Semver\Semver;
13+
use Composer\Semver\VersionParser;
1214
use Packagist\Api\Client;
15+
use UnexpectedValueException;
1316

1417
/**
1518
* SyncPackages command.
@@ -208,18 +211,46 @@ private function checkPHPVersion(array $meta, string $packageConstraint): array
208211
*/
209212
private function checkCakeVersion(array $meta, string $packageConstraint): array
210213
{
211-
$cakeVersions = [
212-
'5.0.0' => 'CakePHP: 5.0',
213-
'4.0.0' => 'CakePHP: 4.0',
214-
'3.0.0' => 'CakePHP: 3.0',
214+
$versions = [
215+
'3' => [0,1,2,3,4,5,6,7,8,9,10],
216+
'4' => [0,1,2,3,4,5,6],
217+
'5' => [0,1,2,3],
215218
];
216219

217-
foreach ($cakeVersions as $version => $label) {
218-
if (Semver::satisfies($version, $packageConstraint) && !in_array($label, $meta)) {
219-
$meta[] = $label;
220+
foreach ($versions as $majorVersionNr => $minorVersions) {
221+
foreach ($minorVersions as $minorVersionNr) {
222+
$minorVersion = sprintf('%s.%s', $majorVersionNr, $minorVersionNr);
223+
$tagLabel = sprintf('CakePHP: %s.%s', $majorVersionNr, $minorVersionNr);
224+
if (
225+
$this->constraintsIntersect($packageConstraint, $minorVersion) &&
226+
!in_array($tagLabel, $meta, true)
227+
) {
228+
$meta[] = $tagLabel;
229+
}
220230
}
221231
}
222232

223233
return $meta;
224234
}
235+
236+
/**
237+
* @param string $leftConstraint
238+
* @param string $rightConstraint
239+
* @return bool
240+
*/
241+
private function constraintsIntersect(string $leftConstraint, string $rightConstraint): bool
242+
{
243+
$versionParser = new VersionParser();
244+
245+
try {
246+
return Intervals::haveIntersections(
247+
$versionParser->parseConstraints($leftConstraint),
248+
$versionParser->parseConstraints($rightConstraint),
249+
);
250+
} catch (UnexpectedValueException) {
251+
return false;
252+
} finally {
253+
Intervals::clear();
254+
}
255+
}
225256
}

src/Controller/PackagesController.php

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ public function index()
7878

7979
$cakephpTags = $this->Packages->Tags->find('list', keyField: 'slug')
8080
->where(['slug LIKE' => 'cakephp-%'])
81-
->orderByDesc('label')
8281
->toArray();
82+
$cakephpTags = $this->sortCakePhpTags($cakephpTags);
8383
$phpTags = $this->Packages->Tags->find('list', keyField: 'slug')
8484
->where(['slug LIKE' => 'php-%'])
8585
->orderByAsc('label')
@@ -114,4 +114,20 @@ protected function hasActiveFilterValue(mixed $value): bool
114114

115115
return (bool)$value;
116116
}
117+
118+
/**
119+
* @param array<string, string> $tags
120+
* @return array<string, string>
121+
*/
122+
protected function sortCakePhpTags(array $tags): array
123+
{
124+
uasort($tags, function (string $left, string $right): int {
125+
$leftVersion = preg_replace('/^CakePHP:\s*/', '', $left) ?: $left;
126+
$rightVersion = preg_replace('/^CakePHP:\s*/', '', $right) ?: $right;
127+
128+
return version_compare($rightVersion, $leftVersion);
129+
});
130+
131+
return $tags;
132+
}
117133
}

src/Model/Entity/Package.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
* @property \Tags\Model\Entity\Tag[] $tags
2020
*
2121
* @property \Tags\Model\Entity\Tag[] $cake_php_tags
22+
* @property array<int, array<\Tags\Model\Entity\Tag>> $cake_php_tag_groups
2223
* @property \Tags\Model\Entity\Tag[] $php_tags
2324
*/
2425
class Package extends Entity
@@ -47,6 +48,39 @@ protected function _getCakePhpTags(): array
4748
});
4849
}
4950

51+
/**
52+
* @return array<int, array<\Tags\Model\Entity\Tag>>
53+
*/
54+
protected function _getCakePhpTagGroups(): array
55+
{
56+
$groups = [];
57+
58+
foreach ($this->cake_php_tags as $tag) {
59+
if (!preg_match('/^CakePHP:\s*(\d+)(?:\.\d+)?$/', $tag->label, $matches)) {
60+
continue;
61+
}
62+
63+
$majorVersion = $matches[1];
64+
$groups[$majorVersion][] = $tag;
65+
}
66+
67+
uksort($groups, static function (string $left, string $right): int {
68+
return version_compare($right, $left);
69+
});
70+
71+
foreach ($groups as &$tags) {
72+
usort($tags, static function ($left, $right): int {
73+
$leftVersion = str_replace('CakePHP: ', '', $left->label);
74+
$rightVersion = str_replace('CakePHP: ', '', $right->label);
75+
76+
return version_compare($rightVersion, $leftVersion);
77+
});
78+
}
79+
unset($tags);
80+
81+
return $groups;
82+
}
83+
5084
/**
5185
* @return array<\Tags\Model\Entity\Tag>
5286
*/

templates/element/Packages/package-tile.php

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,20 +36,32 @@
3636
<p class="mb-2 text-xs font-semibold uppercase tracking-[0.2em] text-slate-500">
3737
<?= __('CakePHP Compatibility') ?>
3838
</p>
39-
<div class="flex flex-wrap gap-2">
40-
<?php foreach ($package->cake_php_tags as $tag): ?>
41-
<?php
42-
$tagQuery = $query;
43-
$tagQuery['cakephp_slugs'] = array_values(array_unique(array_filter([
44-
...((array)($query['cakephp_slugs'] ?? [])),
45-
$tag->slug,
46-
])));
47-
unset($tagQuery['page']);
48-
?>
49-
<a href="<?= h($this->Url->build(['?' => $tagQuery])) ?>"
50-
class="rounded-full bg-cake-red/10 px-3 py-1 text-xs font-medium text-cake-red transition hover:bg-cake-red hover:text-white">
51-
<?= h(str_replace('CakePHP: ', '', $tag->label)) ?>
52-
</a>
39+
<div class="space-y-3">
40+
<?php foreach ($package->cake_php_tag_groups as $majorVersion => $tags): ?>
41+
<div class="flex flex-wrap items-center gap-2 mb-1">
42+
<span class="text-xs font-semibold uppercase tracking-wide text-slate-500">
43+
<?= h($majorVersion) ?>.x
44+
</span>
45+
<?php foreach (array_slice($tags, 0, 6) as $tag): ?>
46+
<?php
47+
$tagQuery = $query;
48+
$tagQuery['cakephp_slugs'] = array_values(array_unique(array_filter([
49+
...((array)($query['cakephp_slugs'] ?? [])),
50+
$tag->slug,
51+
])));
52+
unset($tagQuery['page']);
53+
?>
54+
<a href="<?= h($this->Url->build(['?' => $tagQuery])) ?>"
55+
class="rounded-full bg-cake-red/10 px-3 py-1 text-xs font-medium text-cake-red transition hover:bg-cake-red hover:text-white">
56+
<?= h(str_replace('CakePHP: ', '', $tag->label)) ?>
57+
</a>
58+
<?php endforeach; ?>
59+
<?php if (count($tags) > 6): ?>
60+
<span class="px-1 text-xs font-semibold text-slate-400" aria-label="<?= __('More versions available') ?>">
61+
...
62+
</span>
63+
<?php endif; ?>
64+
</div>
5365
<?php endforeach; ?>
5466
</div>
5567
</div>

0 commit comments

Comments
 (0)