-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathImageReferenceHookHelper.module
188 lines (175 loc) · 7.36 KB
/
ImageReferenceHookHelper.module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<?php
namespace ProcessWire;
// todos: open inputfield in repeaters on page edit load
class ImageReferenceHookHelper extends WireData implements Module
{
/**
* Return an array of module information
*
* @return array
*/
public static function getModuleInfo()
{
return array(
'title' => 'Hook Helper Module for FieldtypeImageReference',
'version' => 212,
'summary' => __('Adds hooks to Pagefiles to restrict deletion of images that are used by FieldtypeImageReference.'),
'author' => 'Gerhard Sitzmann',
'href' => '',
'autoload' => true,
'requires' => array(
'FieldtypeImageReference',
'PHP>=7.1.0',
'ProcessWire>=3.0.120'
)
);
}
public function init()
{
$this->addHookBefore('Pagefiles::delete', $this, 'preventDeletion');
// $this->addHookBefore('InputfieldFile::processInputDeleteFile', $this, 'preventMessage');
// todo: prevent falsy message that file has been deleted. how to remove message from session from within hook function?
// load page in page edit process
// $this->addHookBefore('ProcessPageEdit::loadPage', $this, 'loadImageReferenceVirtualpage');
}
/**
* Executes before an image gets deleted that lives on a page which holds images for FieldtypeImageReference
* If references to that image are found on other pages, deletion is prevented and error messages are shown.
*
* @param Hookevent $event
* @return void
*/
public function preventDeletion(Hookevent $event)
{
$thisFieldname = $event->object->field;
// get fields of type imagereference that have this imagesfield assigned
$fields = $this->getRelevantFields($thisFieldname);
$deleted = $event->arguments(0);
$editPage = $deleted->page;
$imagePageIds = $this->getImagePageIds($fields, $editPage);
$pageid = $deleted->page->id;
if (!in_array($pageid, $imagePageIds)) return;
$filename = $deleted->basename;
$fieldnames = array_map(function ($f) {
return $f->name;
}, $fields);
$pagelist = '';
foreach ($fieldnames as $name) {
$pages = $this->wire('pages')->find("{$name}.filename={$filename}, {$name}.pageid={$pageid}, include=all");
if ($pages->count) {
$label = $pages->first()->getField($name)->label;
$pagelist .= sprintf($this->_("Remove image from field: %s on following pages:"), "<em>{$label}</em>");
$pagelist .= '<ul>';
foreach ($pages as $p) {
$urlParam = "&field={$name}";
if (strpos($p->template->name, 'repeater_') !== false) { // case page is a repeaterpage
// $field = $p->getField($name);
// $inputfield = $field->getInputfield($p);
$repeaterfieldName = substr($p->template->name, strlen('repeater_'));
$urlParam = "&field={$repeaterfieldName}";
}
$p = $this->getPageToEdit($p);
$pagelist .= "<li>"
. $this->_('Page title') . ": <em>{$p->title}</em>, "
. $this->_('Page path') . ": <em>{$p->path}</em>
<a href='{$p->editUrl}{$urlParam}' title='" . $this->_('Edit page in new tab') .
"' target='_blank'><strong>" . $this->_('Edit page') . "</strong></a></li>";
}
$pagelist .= '</ul>';
}
}
if ($pagelist) {
$message = sprintf(
$this->_('You cannot delete image %s as it is being used on other pages.'),
"<em>{$filename}</em>"
) . '<br>';
$message .= "{$pagelist}<br>";
$message .= $this->_('After all references are removed, you may delete the image');
$imgInput = $event->object->field->getInputfield($event->object->page);
$this->error($message, Notice::allowMarkup);
$imgInput->error(sprintf($this->_("Image %s cannot be deleted (follow instructions at the top)"), $filename));
$event->replace = true; // prevents deletion
}
}
/**
* loads an instance of ImageReferenceVirtualpage into page edit screen
*
* @param Hookevent $event
* @return Page ImageReferenceVirtualpage object
*/
public function loadImageReferenceVirtualpage(Hookevent $event) {
$id = $event->arguments(0);
$imagereferencefield = $this->wire('input')->imagereferencefield;
if(!$imagereferencefield) return;
if($id != 999999999) return;
$event->replace = true;
$path = $this->wire('config')->paths->templates . $this->wire('fields')->get($imagereferencefield)->folderpath;
$vPage = new ImageReferenceVirtualpage($path);
$vPage->populateImages();
$event->return = $vPage;
}
/**
* prevent processing of delete request to avoid falsy session notification about deletion
*
* @param Hookevent $event
* @return void
*/
public function preventMessage(Hookevent $event)
{
$this->wire('session')->removeNotices();
}
/**
* Collects IDs of all pages and their children that hold images for fields of type FieldtypeImageReference
*
* @param array $fields all relevant fields of type FieldtypeImageReference
* @param Page $editPage page that is being edited
* @return array array of page ids
*/
public function getImagePageIds($fields, $editPage)
{
$ids = array();
foreach ($fields as $f) {
if($f->imagespage) $ids[] = $f->imagespage;
}
$pages = $this->wire('pages')->find($ids, array('include' => 'hidden'));
foreach ($fields as $field) {
if ($field->includechildren) {
foreach ($pages as $p) {
$pages->add($p->children('include=all'));
}
}
if($field->fromeditpage) $pages->add($editPage);
}
return $pages->explode('id');
}
/**
* get names of imagereference fields that have an imagesfield with name $fieldName assigned
*
* @param string $fieldName name of the imagesfield
* @return array array of fields of type FieldtypeImageReference
*/
public function getRelevantFields($fieldName)
{
$fields = array();
foreach ($this->wire('fields') as $f) {
if (!$f->type instanceof FieldtypeImageReference) continue;
if (( !empty($f->imagesfields) && in_array($fieldName, $f->imagesfields) ) ||(!empty($f->imagesfieldspage) && in_array($fieldName, $f->imagesfieldspage ))) $fields[] = $f;
}
return $fields;
}
/**
* checks if $page is a repeaterpage and travels up the $page's parents until it is not a repeater page
* used so that editors are not presented with links to internal repeater pages
*
* @param Page $page
* @return Page
*/
public function getPageToEdit($page)
{
if (strpos($page->template->name, 'repeater_') === false) return $page;
while (strpos($page->template->name, 'repeater_') !== false) {
$page = $page->getForPage();
}
return $page;
}
}