silverstripe /
silverstripe-cms
| 1 | <?php |
||
| 2 | |||
| 3 | namespace SilverStripe\CMS\Tests\Model; |
||
| 4 | |||
| 5 | use SilverStripe\CMS\Model\SiteTree; |
||
| 6 | use SilverStripe\Control\Director; |
||
| 7 | use SilverStripe\Control\HTTP; |
||
| 8 | use SilverStripe\Dev\SapphireTest; |
||
| 9 | use SilverStripe\Forms\GridField\GridField; |
||
| 10 | use SilverStripe\Versioned\Versioned; |
||
| 11 | |||
| 12 | /** |
||
| 13 | * Tests {@see SiteTreeLinkTracking} broken links feature: LinkTracking |
||
| 14 | */ |
||
| 15 | class SiteTreeBacklinksTest extends SapphireTest |
||
| 16 | { |
||
| 17 | protected static $fixture_file = "SiteTreeBacklinksTest.yml"; |
||
| 18 | |||
| 19 | protected static $required_extensions = [ |
||
| 20 | SiteTree::class => [ |
||
| 21 | SiteTreeBacklinksTest_DOD::class, |
||
| 22 | ], |
||
| 23 | ]; |
||
| 24 | |||
| 25 | protected static $extra_dataobjects = [ |
||
| 26 | SiteTreeBacklinksTestContentObject::class, |
||
| 27 | ]; |
||
| 28 | |||
| 29 | protected function setUp() : void |
||
| 30 | { |
||
| 31 | parent::setUp(); |
||
| 32 | |||
| 33 | // Log in as admin so that we don't run into permission issues. That's not what we're |
||
| 34 | // testing here. |
||
| 35 | $this->logInWithPermission('ADMIN'); |
||
| 36 | |||
| 37 | $page3 = $this->objFromFixture(SiteTree::class, 'page3'); |
||
| 38 | $page3->Content = str_replace( |
||
| 39 | '$page1.ID', |
||
| 40 | $this->objFromFixture(SiteTree::class, 'page1')->ID, |
||
| 41 | $page3->Content |
||
| 42 | ); |
||
| 43 | $page3->write(); |
||
| 44 | } |
||
| 45 | |||
| 46 | public function testSavingPageWithLinkAddsBacklink() |
||
| 47 | { |
||
| 48 | // load page 1 |
||
| 49 | $page1 = $this->objFromFixture(SiteTree::class, 'page1'); |
||
| 50 | |||
| 51 | // assert backlink to page 2 doesn't exist |
||
| 52 | $page2 = $this->objFromFixture(SiteTree::class, 'page2'); |
||
| 53 | $this->assertNotContains( |
||
| 54 | $page2->ID, |
||
| 55 | $page1->BackLinkTracking()->column('ID'), |
||
| 56 | 'Assert backlink to page 2 doesn\'t exist' |
||
| 57 | ); |
||
| 58 | |||
| 59 | // add hyperlink to page 1 on page 2 |
||
| 60 | $page2->Content .= '<p><a href="[sitetree_link,id=' . $page1->ID . ']">Testing page 1 link</a></p>'; |
||
| 61 | $page2->write(); |
||
| 62 | |||
| 63 | // load page 1 |
||
| 64 | $page1 = $this->objFromFixture(SiteTree::class, 'page1'); |
||
| 65 | |||
| 66 | // assert backlink to page 2 exists |
||
| 67 | $this->assertContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 exists'); |
||
| 68 | } |
||
| 69 | |||
| 70 | public function testRemovingLinkFromPageRemovesBacklink() |
||
| 71 | { |
||
| 72 | // load page 1 |
||
| 73 | $page1 = $this->objFromFixture(SiteTree::class, 'page1'); |
||
| 74 | |||
| 75 | // assert backlink to page 3 exits |
||
| 76 | $page3 = $this->objFromFixture(SiteTree::class, 'page3'); |
||
| 77 | $this->assertContains($page3->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 3 exists'); |
||
| 78 | |||
| 79 | // remove hyperlink to page 1 |
||
| 80 | $page3->Content = '<p>No links anymore!</p>'; |
||
| 81 | $page3->write(); |
||
| 82 | |||
| 83 | // load page 1 |
||
| 84 | $page1 = $this->objFromFixture(SiteTree::class, 'page1'); |
||
| 85 | |||
| 86 | // assert backlink to page 3 exists |
||
| 87 | $this->assertNotContains( |
||
| 88 | $page3->ID, |
||
| 89 | $page1->BackLinkTracking()->column('ID'), |
||
| 90 | 'Assert backlink to page 3 doesn\'t exist' |
||
| 91 | ); |
||
| 92 | } |
||
| 93 | |||
| 94 | public function testChangingUrlOnDraftSiteRewritesLink() |
||
| 95 | { |
||
| 96 | // load page 1 |
||
| 97 | $page1 = $this->objFromFixture(SiteTree::class, 'page1'); |
||
| 98 | |||
| 99 | // assert backlink to page 3 exists |
||
| 100 | $page3 = $this->objFromFixture(SiteTree::class, 'page3'); |
||
| 101 | $this->assertContains($page3->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 3 exists'); |
||
| 102 | |||
| 103 | // assert hyperlink to page 1's current url exists on page 3 |
||
| 104 | $links = HTTP::getLinksIn($page3->obj('Content')->forTemplate()); |
||
| 105 | $this->assertContains( |
||
| 106 | Director::baseURL() . 'page1/', |
||
| 107 | $links, |
||
| 108 | 'Assert hyperlink to page 1\'s current url exists on page 3' |
||
| 109 | ); |
||
| 110 | |||
| 111 | // change url of page 1 |
||
| 112 | $page1->URLSegment = 'new-url-segment'; |
||
| 113 | $page1->write(); |
||
| 114 | |||
| 115 | // load page 3 |
||
| 116 | $page3 = $this->objFromFixture(SiteTree::class, 'page3'); |
||
| 117 | |||
| 118 | // assert hyperlink to page 1's new url exists |
||
| 119 | $links = HTTP::getLinksIn($page3->obj('Content')->forTemplate()); |
||
| 120 | $this->assertContains( |
||
| 121 | Director::baseURL() . 'new-url-segment/', |
||
| 122 | $links, |
||
| 123 | 'Assert hyperlink to page 1\'s new url exists on page 3' |
||
| 124 | ); |
||
| 125 | } |
||
| 126 | |||
| 127 | public function testChangingUrlOnLiveSiteRewritesLink() |
||
| 128 | { |
||
| 129 | // publish page 1 & 3 |
||
| 130 | $page1 = $this->objFromFixture(SiteTree::class, 'page1'); |
||
| 131 | $page3 = $this->objFromFixture(SiteTree::class, 'page3'); |
||
| 132 | $this->assertTrue($page1->publishRecursive()); |
||
| 133 | $this->assertTrue($page3->publishRecursive()); |
||
| 134 | |||
| 135 | // load pages from live |
||
| 136 | $page1live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page1->ID); |
||
| 137 | $page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID); |
||
| 138 | |||
| 139 | // assert backlink to page 3 exists |
||
| 140 | $this->assertContains( |
||
| 141 | $page3live->ID, |
||
| 142 | $page1live->BackLinkTracking()->column('ID'), |
||
| 143 | 'Assert backlink to page 3 exists' |
||
| 144 | ); |
||
| 145 | |||
| 146 | // assert hyperlink to page 1's current url exists on page 3 |
||
| 147 | $links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate()); |
||
| 148 | $this->assertContains( |
||
| 149 | Director::baseURL() . 'page1/', |
||
| 150 | $links, |
||
| 151 | 'Assert hyperlink to page 1\'s current url exists on page 3' |
||
| 152 | ); |
||
| 153 | |||
| 154 | // change url of page 1 |
||
| 155 | $page1live->URLSegment = 'new-url-segment'; |
||
| 156 | $page1live->writeToStage('Live'); |
||
| 157 | |||
| 158 | // load page 3 from live |
||
| 159 | $page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID); |
||
| 160 | |||
| 161 | // assert hyperlink to page 1's new url exists |
||
| 162 | Versioned::set_stage(Versioned::LIVE); |
||
| 163 | $links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate()); |
||
| 164 | $this->assertContains( |
||
| 165 | Director::baseURL() . 'new-url-segment/', |
||
| 166 | $links, |
||
| 167 | 'Assert hyperlink to page 1\'s new url exists on page 3' |
||
| 168 | ); |
||
| 169 | } |
||
| 170 | |||
| 171 | public function testPublishingPageWithModifiedUrlRewritesLink() |
||
| 172 | { |
||
| 173 | // publish page 1 & 3 |
||
| 174 | $page1 = $this->objFromFixture(SiteTree::class, 'page1'); |
||
| 175 | $page3 = $this->objFromFixture(SiteTree::class, 'page3'); |
||
| 176 | |||
| 177 | $this->assertTrue($page1->publishRecursive()); |
||
| 178 | $this->assertTrue($page3->publishRecursive()); |
||
| 179 | |||
| 180 | // load page 3 from live |
||
| 181 | $page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID); |
||
| 182 | |||
| 183 | // assert hyperlink to page 1's current url exists |
||
| 184 | $links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate()); |
||
| 185 | $this->assertContains( |
||
| 186 | Director::baseURL() . 'page1/', |
||
| 187 | $links, |
||
| 188 | 'Assert hyperlink to page 1\'s current url exists on page 3' |
||
| 189 | ); |
||
| 190 | |||
| 191 | // rename url of page 1 on stage |
||
| 192 | $page1->URLSegment = 'new-url-segment'; |
||
| 193 | $page1->write(); |
||
| 194 | |||
| 195 | // assert hyperlink to page 1's current publish url exists |
||
| 196 | $page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID); |
||
| 197 | Versioned::set_stage(Versioned::LIVE); |
||
| 198 | $links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate()); |
||
| 199 | $this->assertContains( |
||
| 200 | Director::baseURL() . 'page1/', |
||
| 201 | $links, |
||
| 202 | 'Assert hyperlink to page 1\'s current published url exists on page 3' |
||
| 203 | ); |
||
| 204 | |||
| 205 | |||
| 206 | // publish page 1 |
||
| 207 | $this->assertTrue($page1->publishRecursive()); |
||
| 208 | |||
| 209 | // assert hyperlink to page 1's new published url exists |
||
| 210 | $page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID); |
||
| 211 | $links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate()); |
||
| 212 | $this->assertContains( |
||
| 213 | Director::baseURL() . 'new-url-segment/', |
||
| 214 | $links, |
||
| 215 | 'Assert hyperlink to page 1\'s new published url exists on page 3' |
||
| 216 | ); |
||
| 217 | } |
||
| 218 | |||
| 219 | public function testPublishingPageWithModifiedLinksRewritesLinks() |
||
| 220 | { |
||
| 221 | // publish page 1 & 3 |
||
| 222 | $page1 = $this->objFromFixture(SiteTree::class, 'page1'); |
||
| 223 | $page3 = $this->objFromFixture(SiteTree::class, 'page3'); |
||
| 224 | $this->assertTrue($page1->publishRecursive()); |
||
| 225 | $this->assertTrue($page3->publishRecursive()); |
||
| 226 | |||
| 227 | // assert hyperlink to page 1's current url exists |
||
| 228 | $links = HTTP::getLinksIn($page3->obj('Content')->forTemplate()); |
||
| 229 | $this->assertContains( |
||
| 230 | Director::baseURL() . 'page1/', |
||
| 231 | $links, |
||
| 232 | 'Assert hyperlink to page 1\'s current published url exists on page 3' |
||
| 233 | ); |
||
| 234 | |||
| 235 | // change page 1 url on draft |
||
| 236 | $page1->URLSegment = 'new-url-segment'; |
||
| 237 | |||
| 238 | // save page 1 |
||
| 239 | $page1->write(); |
||
| 240 | |||
| 241 | // assert page 3 on draft contains new page 1 url |
||
| 242 | $page3 = $this->objFromFixture(SiteTree::class, 'page3'); |
||
| 243 | $links = HTTP::getLinksIn($page3->obj('Content')->forTemplate()); |
||
| 244 | $this->assertContains( |
||
| 245 | Director::baseURL() . 'new-url-segment/', |
||
| 246 | $links, |
||
| 247 | 'Assert hyperlink to page 1\'s current draft url exists on page 3' |
||
| 248 | ); |
||
| 249 | |||
| 250 | // publish page 3 |
||
| 251 | $this->assertTrue($page3->publishRecursive()); |
||
| 252 | |||
| 253 | // assert page 3 on published site contains old page 1 url |
||
| 254 | $page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID); |
||
| 255 | Versioned::set_stage(Versioned::LIVE); |
||
| 256 | $links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate()); |
||
| 257 | $this->assertContains( |
||
| 258 | Director::baseURL() . 'page1/', |
||
| 259 | $links, |
||
| 260 | 'Assert hyperlink to page 1\'s current published url exists on page 3' |
||
| 261 | ); |
||
| 262 | |||
| 263 | // publish page 1 |
||
| 264 | $this->assertTrue($page1->publishRecursive()); |
||
| 265 | |||
| 266 | // assert page 3 on published site contains new page 1 url |
||
| 267 | $page3live = Versioned::get_one_by_stage(SiteTree::class, 'Live', '"SiteTree"."ID" = ' . $page3->ID); |
||
| 268 | $links = HTTP::getLinksIn($page3live->obj('Content')->forTemplate()); |
||
| 269 | $this->assertContains( |
||
| 270 | Director::baseURL() . 'new-url-segment/', |
||
| 271 | $links, |
||
| 272 | 'Assert hyperlink to page 1\'s current published url exists on page 3' |
||
| 273 | ); |
||
| 274 | } |
||
| 275 | |||
| 276 | public function testLinkTrackingOnExtraContentFields() |
||
| 277 | { |
||
| 278 | /** @var SiteTree $page1 */ |
||
| 279 | $page1 = $this->objFromFixture(SiteTree::class, 'page1'); |
||
| 280 | /** @var SiteTree $page2 */ |
||
| 281 | $page2 = $this->objFromFixture(SiteTree::class, 'page2'); |
||
| 282 | $page1->publishRecursive(); |
||
| 283 | $page2->publishRecursive(); |
||
| 284 | |||
| 285 | // assert backlink to page 2 doesn't exist |
||
| 286 | $this->assertNotContains( |
||
| 287 | $page2->ID, |
||
| 288 | $page1->BackLinkTracking()->column('ID'), |
||
| 289 | 'Assert backlink to page 2 doesn\'t exist' |
||
| 290 | ); |
||
| 291 | |||
| 292 | // add hyperlink to page 1 on page 2 |
||
| 293 | $page2->ExtraContent .= '<p><a href="[sitetree_link,id=' . $page1->ID . ']">Testing page 1 link</a></p>'; |
||
| 294 | $page2->write(); |
||
| 295 | $page2->publishRecursive(); |
||
| 296 | |||
| 297 | // assert backlink to page 2 exists |
||
| 298 | $this->assertContains($page2->ID, $page1->BackLinkTracking()->column('ID'), 'Assert backlink to page 2 exists'); |
||
| 299 | |||
| 300 | // update page1 url |
||
| 301 | $page1 = $this->objFromFixture(SiteTree::class, 'page1'); |
||
| 302 | $page1->URLSegment = "page1-new-url"; |
||
| 303 | $page1->write(); |
||
| 304 | |||
| 305 | // confirm that draft link on page2 has been rewritten |
||
| 306 | $page2 = $this->objFromFixture(SiteTree::class, 'page2'); |
||
| 307 | $this->assertEquals( |
||
| 308 | '<p><a href="' . Director::baseURL() . 'page1-new-url/">Testing page 1 link</a></p>', |
||
| 309 | $page2->obj('ExtraContent')->forTemplate() |
||
| 310 | ); |
||
| 311 | |||
| 312 | // confirm that published link hasn't |
||
| 313 | $page2Live = Versioned::get_one_by_stage(SiteTree::class, "Live", "\"SiteTree\".\"ID\" = $page2->ID"); |
||
| 314 | Versioned::set_stage(Versioned::LIVE); |
||
| 315 | $this->assertEquals( |
||
| 316 | '<p><a href="' . Director::baseURL() . 'page1/">Testing page 1 link</a></p>', |
||
| 317 | $page2Live->obj('ExtraContent')->forTemplate() |
||
| 318 | ); |
||
| 319 | |||
| 320 | // publish page1 and confirm that the link on the published page2 has now been updated |
||
| 321 | $page1->publishRecursive(); |
||
| 322 | $page2Live = Versioned::get_one_by_stage(SiteTree::class, "Live", "\"SiteTree\".\"ID\" = $page2->ID"); |
||
| 323 | $this->assertEquals( |
||
| 324 | '<p><a href="' . Director::baseURL() . 'page1-new-url/">Testing page 1 link</a></p>', |
||
| 325 | $page2Live->obj('ExtraContent')->forTemplate() |
||
| 326 | ); |
||
| 327 | |||
| 328 | // Edit draft again |
||
| 329 | Versioned::set_stage(Versioned::DRAFT); |
||
| 330 | $page2->ExtraContent = '<p>No links anymore!</p>'; |
||
| 331 | $page2->write(); |
||
| 332 | |||
| 333 | // assert backlink to page 2 no longer exists |
||
| 334 | $this->assertNotContains( |
||
| 335 | $page2->ID, |
||
| 336 | $page1->BackLinkTracking()->column('ID'), |
||
| 337 | 'Assert backlink to page 2 has been removed' |
||
| 338 | ); |
||
| 339 | } |
||
| 340 | |||
| 341 | public function testLinkTrackingWithUntitledObjectsDisplaysAReadableIdentifier() |
||
| 342 | { |
||
| 343 | $page = $this->objFromFixture(SiteTree::class, 'page2'); |
||
| 344 | |||
| 345 | $referencingObject = new SiteTreeBacklinksTestContentObject(); |
||
| 346 | $referencingObject->Content = '<p><a href="[sitetree_link,id=' |
||
|
0 ignored issues
–
show
Bug
Best Practice
introduced
by
Loading history...
|
|||
| 347 | . $page->ID |
||
| 348 | . ']">Page 2</a></p>'; |
||
| 349 | // Title purposely not set - this is the coverage case for this test |
||
| 350 | $referencingObject->write(); |
||
| 351 | |||
| 352 | /** @var GridField $gridField */ |
||
| 353 | $gridField = $page->getCMSFields()->dataFieldByName('DependentPages'); |
||
| 354 | |||
| 355 | // Prepare and sanity check |
||
| 356 | $this->assertNotNull($gridField); |
||
| 357 | $list = $gridField->getList(); |
||
| 358 | $this->assertEquals(1, $list->count()); |
||
| 359 | |||
| 360 | $content = $gridField->getColumnContent($list->first(), 'Title'); |
||
| 361 | |||
| 362 | $this->assertStringContainsString('Untitled Backlink test content object', $content); |
||
| 363 | } |
||
| 364 | } |
||
| 365 |