Skip to content

Commit 7dab612

Browse files
Fix issue with repeater files when combined with $config->pagefilesSecure option. It was using the secure URL when it shouldn't.
1 parent 393e420 commit 7dab612

File tree

4 files changed

+256
-101
lines changed

4 files changed

+256
-101
lines changed

wire/core/Data.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,25 @@ public function set($key, $value) {
4444
return $this;
4545
}
4646

47+
/**
48+
* Same as set() but triggers no change tracking or hooks
49+
*
50+
* If trackChanges is false, then this is no different than set().
51+
* If trackChanges is true, then the value will be set but not recorded in the changes list.
52+
*
53+
* @param string $key
54+
* @param mixed $value
55+
* @return this
56+
*
57+
*/
58+
public function setQuietly($key, $value) {
59+
$track = $this->trackChanges;
60+
if($track) $this->setTrackChanges(false);
61+
$this->set($key, $value);
62+
if($track) $this->setTrackChanges(true);
63+
return $this;
64+
}
65+
4766
/**
4867
* Is $value1 equal to $value2?
4968
*

wire/modules/Fieldtype/FieldtypeRepeater/FieldtypeRepeater.module

Lines changed: 15 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
* Copyright (C) 2012 by Ryan Cramer
1414
* Licensed under GNU/GPL v2, see LICENSE.TXT
1515
*
16-
* http://www.processwire.com
17-
* http://www.ryancramer.com
16+
* http://processwire.com
1817
*
1918
*/
2019

@@ -24,7 +23,7 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
2423
return array(
2524
'title' => __('Repeater', __FILE__), // Module Title
2625
'summary' => __('Maintains a collection of fields that are repeated for any number of times.', __FILE__), // Module Summary
27-
'version' => 100,
26+
'version' => 101,
2827
'autoload' => true,
2928
'installs' => 'InputfieldRepeater'
3029
);
@@ -61,6 +60,10 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
6160
*
6261
*/
6362
public function __construct() {
63+
64+
require_once(dirname(__FILE__) . '/RepeaterPage.php');
65+
require_once(dirname(__FILE__) . '/RepeaterPageArray.php');
66+
6467
$this->set('repeatersRootPageID', 0);
6568
}
6669

@@ -80,6 +83,12 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
8083
public function ready() {
8184
if(wire('page')->process == 'ProcessPageEdit') $this->addHookBefore('ProcessPageEdit::ajaxSave', $this, 'hookProcessPageEditAjaxSave');
8285
$this->addHookBefore('PageFinder::getQuery', $this, 'hookPageFinderGetQuery');
86+
87+
// make sure that all templates used by repeater pages enforce a Page type of RepeaterPage
88+
foreach(wire('templates') as $template) {
89+
if(strpos($template->name, self::templateNamePrefix) === false) continue;
90+
$template->setQuietly('pageClass', 'RepeaterPage');
91+
}
8392
}
8493

8594
/**
@@ -410,12 +419,14 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
410419
*/
411420
public function getBlankRepeaterPage(Page $page, Field $field) {
412421
$parent = $this->getRepeaterPageParent($page, $field);
413-
$readyPage = new Page();
422+
$readyPage = new RepeaterPage();
414423
$readyPage->template = $this->getRepeaterTemplate($field);
415424
if($parent->id) $readyPage->parent = $parent;
416425
$readyPage->addStatus(Page::statusHidden);
417426
$readyPage->addStatus(Page::statusUnpublished);
418427
$readyPage->name = $this->getUniqueRepeaterPageName();
428+
$readyPage->setForPage($page);
429+
$readyPage->setForField($field);
419430
return $readyPage;
420431
}
421432

@@ -1266,100 +1277,3 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
12661277

12671278
}
12681279

1269-
/**
1270-
* Special PageArray for use by repeaters that includes a getNewItem() method
1271-
*
1272-
*/
1273-
1274-
class RepeaterPageArray extends PageArray {
1275-
1276-
/**
1277-
* The page that contains the repeater field (not the parent in the repeaters structure)
1278-
*
1279-
*/
1280-
protected $parent = null;
1281-
1282-
/**
1283-
* The repeater field (from $this->fields API var)
1284-
*
1285-
*/
1286-
protected $field = null;
1287-
1288-
public function __construct(Page $parent, Field $field) {
1289-
$this->setParent($parent);
1290-
$this->setField($field);
1291-
}
1292-
1293-
public function setParent(Page $parent) { $this->parent = $parent; }
1294-
public function getParent() { return $this->parent; }
1295-
public function setField(Field $field) { $this->field = $field; }
1296-
public function getField() { return $this->field; }
1297-
1298-
/**
1299-
* Alias of getNewItem() kept for backwards compatibility
1300-
*
1301-
*/
1302-
public function getNew() { return $this->getNewItem(); }
1303-
1304-
/**
1305-
* Return a new repeater item ready for use
1306-
*
1307-
* If there are ready items, it will return the first ready item
1308-
* Otherwise it'll create a new item
1309-
*
1310-
* This method is different from FieldtypeRepeater::getBlankRepeaterPage:
1311-
* 1. It returns an already existing readyPage, if it exists (otherwise it creates a new page)
1312-
* 2. The returned page is in a non-hidden published state, so will appear as soon as it is saved
1313-
*
1314-
* Note that this method has no relation/similarity to the makeNew() method.
1315-
*
1316-
* @return Page
1317-
*
1318-
*/
1319-
public function getNewItem() {
1320-
1321-
$page = null;
1322-
$of = $this->parent->of(false);
1323-
1324-
foreach($this as $item) {
1325-
if($item->is(Page::statusUnpublished) && $item->is(Page::statusHidden)) {
1326-
$page = $item;
1327-
break;
1328-
}
1329-
}
1330-
1331-
if(is_null($page)) {
1332-
$page = $this->field->type->getBlankRepeaterPage($this->parent, $this->field);
1333-
$this->add($page);
1334-
} else {
1335-
$this->trackChange('add');
1336-
}
1337-
1338-
$page->of(false);
1339-
$page->removeStatus(Page::statusUnpublished);
1340-
$page->removeStatus(Page::statusHidden);
1341-
$page->sort = $this->count();
1342-
1343-
if($of) $this->parent->of(true);
1344-
1345-
return $page;
1346-
}
1347-
1348-
/**
1349-
* Creates a new blank instance of a RepeaterPageArray. For internal use.
1350-
*
1351-
* Note that this method has no relation/similarity to the getNewItem()/getNew() methods.
1352-
*
1353-
* @param array $items Array of items to populate (optional)
1354-
* @return WireArray
1355-
*
1356-
*/
1357-
public function makeNew() {
1358-
$class = get_class($this);
1359-
$newArray = new $class($this->parent, $this->field);
1360-
return $newArray;
1361-
}
1362-
1363-
1364-
}
1365-
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
3+
/**
4+
* RepeaterPage represents an individual repeater page item
5+
*
6+
* ProcessWire 2.x
7+
* Copyright (C) 2012 by Ryan Cramer
8+
* Licensed under GNU/GPL v2, see LICENSE.TXT
9+
*
10+
* http://processwire.com
11+
*
12+
*/
13+
14+
class RepeaterPage extends Page {
15+
16+
/**
17+
* Page instance that has this repeater item on it
18+
*
19+
*/
20+
protected $forPage = null;
21+
22+
/**
23+
* Field instance that contains this repeater item
24+
*
25+
*/
26+
protected $forField = null;
27+
28+
/**
29+
* Set the page that owns this repeater item
30+
*
31+
* @param Page $forPage
32+
* @return this
33+
*
34+
*/
35+
public function setForPage(Page $forPage) {
36+
$this->forPage = $forPage;
37+
return $this;
38+
}
39+
40+
/**
41+
* Return the page that this repeater item is for
42+
*
43+
* @return Page
44+
*
45+
*/
46+
public function getForPage() {
47+
48+
if(!is_null($this->forPage)) return $this->forPage;
49+
50+
// ownerPage is usually set by FieldtypeRepeater::wakeupValue
51+
// but if this repeater was loaded from somewhere else, that won't
52+
// have happened, so we have to determine it from it's location
53+
54+
$parentName = $this->parent()->name;
55+
$prefix = FieldtypeRepeater::repeaterPageNamePrefix; // for-page-
56+
57+
if(strpos($parentName, $prefix) === 0) {
58+
// determine owner page from parent name in format: for-page-1234
59+
$forID = (int) substr($parentName, strlen($prefix));
60+
$this->forPage = wire('pages')->get($forID);
61+
} else {
62+
// this probably can't occur, but here just in case
63+
$this->forPage = new NullPage();
64+
}
65+
66+
return $this->forPage;
67+
}
68+
69+
/**
70+
* Set the field that owns this repeater item
71+
*
72+
* @param Field $forField
73+
* @return this
74+
*
75+
*/
76+
public function setForField(Field $forField) {
77+
$this->forField = $forField;
78+
return $this;
79+
}
80+
81+
/**
82+
* Return the field that this repeater item belongs to
83+
*
84+
* @return Field
85+
*
86+
*/
87+
public function getForField() {
88+
if(!is_null($this->forField)) return $this->forField;
89+
90+
$grandparentName = $this->parent()->parent()->name;
91+
$prefix = FieldtypeRepeater::fieldPageNamePrefix; // for-field-
92+
93+
if(strpos($grandparentName, $prefix) === 0) {
94+
// determine field from grandparent name in format: for-field-1234
95+
$forID = (int) substr($grandparentName, strlen($prefix));
96+
$this->forField = wire('fields')->get($forID);
97+
}
98+
99+
return $this->forPage;
100+
}
101+
102+
/**
103+
* Is this page public?
104+
*
105+
* In this case, we delegate that decision to the owner page.
106+
*
107+
* @return bool
108+
*
109+
*/
110+
public function isPublic() {
111+
if($this->is(Page::statusUnpublished)) return false;
112+
return $this->getForPage()->isPublic();
113+
}
114+
}
115+

0 commit comments

Comments
 (0)