Completed
Push — master ( bbb282...43d0b8 )
by Daniel
25s
created

CMSBatchAction::applicablePages()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Admin;
4
5
use SilverStripe\ORM\SS_List;
6
use SilverStripe\ORM\DataObject;
7
use SilverStripe\ORM\Versioning\Versioned;
8
use Object;
9
use Controller;
10
use Convert;
11
12
13
/**
14
 * A class representing back actions.
15
 * See CMSMain.BatchActions.js on how to add custom javascript
16
 * functionality.
17
 *
18
 * <code>
19
 * CMSMain::register_batch_action('publishitems', new CMSBatchAction('doPublish',
20
 * 	_t('CMSBatchActions.PUBLISHED_PAGES', 'published %d pages')));
21
 * </code>
22
 *
23
 * @package framework
24
 * @subpackage admin
25
 */
26
abstract class CMSBatchAction extends Object {
27
28
	protected $managedClass = 'SilverStripe\\CMS\\Model\\SiteTree';
29
30
	/**
31
	 * The the text to show in the dropdown for this action
32
	 */
33
	abstract public function getActionTitle();
34
35
	/**
36
	 * Run this action for the given set of pages.
37
	 * Return a set of status-updated JavaScript to return to the CMS.
38
	 *
39
	 * @param SS_List $objs
40
	 * @return string
41
	 */
42
	abstract public function run(SS_List $objs);
43
44
	/**
45
	 * Helper method for responding to a back action request
46
	 * @param string $successMessage The message to return as a notification.
47
	 * Can have up to two %d's in it. The first will be replaced by the number of successful
48
	 * changes, the second by the number of failures
49
	 * @param array $status A status array like batchactions builds. Should be
50
	 * key => value pairs, the key can be any string: "error" indicates errors, anything
51
	 * else indicates a type of success. The value is an array. We don't care what's in it,
52
	 * we just use count($value) to find the number of items that succeeded or failed
53
	 * @return string
54
	 */
55
	public function response($successMessage, $status) {
56
		$count = 0;
57
		$errors = 0;
58
59
		foreach($status as $k => $v) {
60
			switch($k) {
61
				case 'error':
62
					$errors += count($v);
63
					break;
64
				case 'success':
65
					$count += count($v);
66
					break;
67
			}
68
		}
69
70
		$response = Controller::curr()->getResponse();
71
72
		if($response) {
73
			$response->setStatusCode(
74
				200,
75
				sprintf($successMessage, $count, $errors)
76
			);
77
		}
78
79
		return Convert::raw2json($status);
80
	}
81
82
	/**
83
	 * Helper method for processing batch actions.
84
	 * Returns a set of status-updating JavaScript to return to the CMS.
85
	 *
86
	 * @param SS_List $objs The SS_List of objects to perform this batch action
87
	 * on.
88
	 * @param string $helperMethod The method to call on each of those objects.
89
	 * @param string $successMessage
90
	 * @param array $arguments
91
	 * @return string JSON encoded map in the following format:
92
	 *  {
93
	 *     'modified': {
94
	 *       3: {'TreeTitle': 'Page3'},
95
	 *       5: {'TreeTitle': 'Page5'}
96
	 *     },
97
	 *     'deleted': {
98
	 *       // all deleted pages
99
	 *     }
100
	 *  }
101
	 */
102
	public function batchaction(SS_List $objs, $helperMethod, $successMessage, $arguments = array()) {
103
		$status = array('modified' => array(), 'error' => array(), 'deleted' => array(), 'success' => array());
104
105
		foreach($objs as $obj) {
106
107
			// Perform the action
108
			$id = $obj->ID;
109
			if (!call_user_func_array(array($obj, $helperMethod), $arguments)) {
110
				$status['error'][$id] = $id;
111
			} else {
112
				$status['success'][$id] = $id;
113
			}
114
115
			// Now make sure the tree title is appropriately updated
116
			$publishedRecord = DataObject::get_by_id($this->managedClass, $id);
117
			if ($publishedRecord) {
118
				$status['modified'][$id] = array(
119
					'TreeTitle' => $publishedRecord->TreeTitle,
120
				);
121
			} else {
122
				$status['deleted'][$id] = $id;
123
			}
124
			$obj->destroy();
125
			unset($obj);
126
		}
127
128
		return $this->response($successMessage, $status);
129
	}
130
131
132
133
	/**
134
	 * Helper method for applicablePages() methods.  Acts as a skeleton implementation.
135
	 *
136
	 * @param array $ids The IDs passed to applicablePages
137
	 * @param string $methodName The canXXX() method to call on each page to check if the action is applicable
138
	 * @param bool $checkStagePages Set to true if you want to check stage pages
139
	 * @param bool $checkLivePages Set to true if you want to check live pages (e.g, for deleted-from-draft)
140
	 * @return array
141
	 */
142
	public function applicablePagesHelper($ids, $methodName, $checkStagePages = true, $checkLivePages = true) {
143
		if(!is_array($ids)) user_error("Bad \$ids passed to applicablePagesHelper()", E_USER_WARNING);
144
		if(!is_string($methodName)) user_error("Bad \$methodName passed to applicablePagesHelper()", E_USER_WARNING);
145
146
		$applicableIDs = array();
147
148
		$managedClass = $this->managedClass;
149
		$draftPages = DataObject::get($managedClass)->byIDs($ids);
150
151
		// Filter out the live-only ids
152
		$onlyOnLive = array_fill_keys($ids, true);
153
		if($checkStagePages) {
154
			foreach($draftPages as $obj) {
155
				unset($onlyOnLive[$obj->ID]);
156
				if($obj->$methodName()) $applicableIDs[] = $obj->ID;
157
			}
158
		}
159
		$onlyOnLive = array_keys($onlyOnLive);
160
161
		if($checkLivePages && $onlyOnLive && Object::has_extension($managedClass, 'SilverStripe\\ORM\\Versioning\\Versioned')) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $onlyOnLive of type array<integer|string> is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
162
			// Get the pages that only exist on live (deleted from stage)
163
			$livePages = Versioned::get_by_stage($managedClass, "Live")->byIDs($onlyOnLive);
164
			foreach($livePages as $obj) {
165
				if($obj->$methodName()) $applicableIDs[] = $obj->ID;
166
			}
167
		}
168
169
		return $applicableIDs;
170
	}
171
172
173
	// if your batchaction has parameters, return a FieldList here
174
	public function getParameterFields() {
175
		return false;
176
	}
177
178
	/**
179
	 * If you wish to restrict the batch action to some users, overload this function.
180
	 */
181
	public function canView() {
182
		return true;
183
	}
184
185
	/**
186
	 * Given a list of object IDs, filter out which items can have this batch action applied
187
	 * to them.
188
	 *
189
	 * @param array $ids List of object ids
190
	 * @return array Filtered list of $ids
191
	 */
192
	public function applicablePages($ids) {
193
		return $ids;
194
	}
195
}
196