|
4 | 4 |
|
5 | 5 | use craft\elements\Entry; |
6 | 6 | use craft\fieldlayoutelements\CustomField; |
| 7 | +use craft\helpers\Html; |
| 8 | +use craft\helpers\UrlHelper; |
7 | 9 | use craft\models\EntryType; |
8 | 10 | use craft\models\FieldLayout; |
9 | 11 | use craft\models\FieldLayoutTab; |
|
135 | 137 | ->and($html)->not->toContain('onerror'); |
136 | 138 | }); |
137 | 139 |
|
| 140 | +it('resolves CraftLink fragments after the linked entry URI changes', function(string $marker, bool $explicitSite, string $suffix) { |
| 141 | + $siteId = $this->entry->siteId; |
| 142 | + $settings = $this->section->getSiteSettings(); |
| 143 | + $settings[$siteId]->hasUrls = true; |
| 144 | + $settings[$siteId]->uriFormat = 'news/{slug}'; |
| 145 | + $this->section->setSiteSettings($settings); |
| 146 | + expect(Craft::$app->getEntries()->saveSection($this->section))->toBeTrue(); |
| 147 | + expect(Craft::$app->getElements()->saveElement($this->entry))->toBeTrue(); |
| 148 | + $oldUrl = $this->entry->getUrl(); |
| 149 | + $ref = $marker . 'entry:' . $this->entry->id . ($explicitSite ? '@' . $siteId : ''); |
| 150 | + $sourceUrl = UrlHelper::urlWithParams($oldUrl, Html::decode($suffix)); |
| 151 | + $source = '<p><a href="' . Html::encode($sourceUrl) . $ref . '" target="_blank">Read more</a></p>'; |
| 152 | + $value = $this->tableField->normalizeValue([ |
| 153 | + 'columns' => [['heading' => 'Reference', 'type' => 'richtext']], |
| 154 | + 'rows' => [[$source]], |
| 155 | + ], $this->entry); |
| 156 | + $stored = $value->toStorage(); |
| 157 | + |
| 158 | + $this->entry->slug = 'updated-link'; |
| 159 | + expect(Craft::$app->getElements()->saveElement($this->entry))->toBeTrue(); |
| 160 | + $currentUrl = $this->entry->getUrl(); |
| 161 | + $expectedUrl = Html::encode(UrlHelper::urlWithParams($currentUrl, Html::decode($suffix))); |
| 162 | + expect($currentUrl)->not->toBe($oldUrl); |
| 163 | + |
| 164 | + // An explicit link site must win over the owning cell's site. |
| 165 | + $value->siteId = $explicitSite ? 999999 : $siteId; |
| 166 | + $html = (string)$value->getTable(); |
| 167 | + expect($html)->toContain('href="' . $expectedUrl . '"') |
| 168 | + ->and($html)->toContain('target="_blank"') |
| 169 | + ->and($html)->not->toContain($marker . 'entry:', '{entry:') |
| 170 | + ->and($value->toStorage())->toBe($stored); |
| 171 | + |
| 172 | + // Standalone values without an owner still use Craft's default site. |
| 173 | + $standalone = verbb\tablemaker\helpers\TableValue::normalize($stored); |
| 174 | + expect((string)$standalone->getTable())->toContain('href="' . $expectedUrl . '"'); |
| 175 | +})->with([ |
| 176 | + 'explicit site' => ['#', true, ''], |
| 177 | + 'owning site and suffix' => ['#', false, '?source=table&page=2#details'], |
| 178 | + 'encoded marker' => ['%23', true, '?source=table#details'], |
| 179 | +]); |
| 180 | + |
| 181 | +it('keeps ordinary links and falls back to saved URLs for missing CraftLink elements', function() { |
| 182 | + $source = '<p><a href="https://example.test/page#details">Anchor</a> ' |
| 183 | + . '<a href="https://example.test/old?source=table#details#entry:999999999@1">Missing entry</a> ' |
| 184 | + . '<a href="https://example.test/category#category:999999999">Missing category</a> ' |
| 185 | + . '<a href="https://example.test/file.pdf%23asset:999999999">Missing asset</a></p>' |
| 186 | + . '<p><code>href="https://example.test/sample#entry:123"</code></p>'; |
| 187 | + $value = $this->tableField->normalizeValue([ |
| 188 | + 'columns' => [['heading' => 'Reference', 'type' => 'richtext']], |
| 189 | + 'rows' => [[$source]], |
| 190 | + ], $this->entry); |
| 191 | + |
| 192 | + expect((string)$value->getTable())->toContain( |
| 193 | + 'href="https://example.test/page#details"', |
| 194 | + 'href="https://example.test/old?source=table#details"', |
| 195 | + 'href="https://example.test/category"', |
| 196 | + 'href="https://example.test/file.pdf"', |
| 197 | + '<code>href="https://example.test/sample#entry:123"</code>', |
| 198 | + )->not->toContain('#entry:999999999', '#category:', '%23asset:'); |
| 199 | +}); |
| 200 | + |
138 | 201 | it('rejects invalid numbers without replacing saved table content', function(string $number) { |
139 | 202 | $handle = $this->tableField->handle; |
140 | 203 | $this->entry->setFieldValueFromRequest($handle, [ |
|
0 commit comments