1 |
85ad3d82
|
Assos Assos
|
<?php
|
2 |
|
|
|
3 |
|
|
/**
|
4 |
|
|
* @file
|
5 |
|
|
* Import/Export functionality provided by Flag module.
|
6 |
|
|
*/
|
7 |
|
|
|
8 |
|
|
/**
|
9 |
|
|
* Export a flag to code.
|
10 |
|
|
*
|
11 |
fd5a8e62
|
Assos Assos
|
* @param array $flags
|
12 |
85ad3d82
|
Assos Assos
|
* An array of flag objects, or flag name.
|
13 |
fd5a8e62
|
Assos Assos
|
* @param string $module
|
14 |
85ad3d82
|
Assos Assos
|
* Optional. The name of the module that will be created if exporting to use
|
15 |
|
|
* in hook_flag_default_flags().
|
16 |
|
|
*/
|
17 |
|
|
function flag_export_flags($flags = array(), $module = '', $indent = '') {
|
18 |
76e2e7c3
|
Assos Assos
|
// For features_var_export() (optional).
|
19 |
|
|
module_load_include('inc', 'features', 'features.export');
|
20 |
85ad3d82
|
Assos Assos
|
$output = $indent . '$flags = array();' . "\n";
|
21 |
|
|
foreach ($flags as $item) {
|
22 |
|
|
if (is_object($item)) {
|
23 |
|
|
$flag = $item;
|
24 |
|
|
}
|
25 |
|
|
else {
|
26 |
|
|
// We got just the flag name, for example from the features
|
27 |
|
|
// implementation.
|
28 |
|
|
if (!($flag = flag_load($item, TRUE))) {
|
29 |
|
|
continue;
|
30 |
|
|
}
|
31 |
|
|
}
|
32 |
|
|
if (!$flag->is_compatible()) {
|
33 |
|
|
drupal_set_message(t('Could not export flag %flag-name: Your flag was created by a different version of the Flag module than is now being used.', array('%flag-name' => $flag->name)), 'error');
|
34 |
|
|
continue;
|
35 |
|
|
}
|
36 |
|
|
|
37 |
|
|
$flag->api_version = FLAG_API_VERSION;
|
38 |
|
|
$new_flag = (array) $flag;
|
39 |
|
|
|
40 |
|
|
if (!empty($module)) {
|
41 |
|
|
// Even though Flag adds the module name itself later, we add the module
|
42 |
|
|
// name here for reference by other modules (such as Features).
|
43 |
|
|
$new_flag['module'] = $module;
|
44 |
|
|
// Lock the flag name, as is normally desired by modules using
|
45 |
|
|
// hook_flag_default_flags(), and needed by Features.
|
46 |
|
|
$new_flag['locked'] = array('name');
|
47 |
|
|
}
|
48 |
|
|
// Allow other modules to change the exported flag.
|
49 |
|
|
drupal_alter('flag_export', $new_flag);
|
50 |
|
|
|
51 |
|
|
// Remove properties we don't export.
|
52 |
|
|
$unset_properties = array(
|
53 |
|
|
// Remove the flag ID.
|
54 |
|
|
'fid',
|
55 |
|
|
// The name is emitted as the key for the array.
|
56 |
|
|
'name',
|
57 |
|
|
// The entity info is just used as helper data.
|
58 |
|
|
'entity_info',
|
59 |
|
|
// Remove roles.
|
60 |
|
|
'roles',
|
61 |
|
|
// Remove errors.
|
62 |
|
|
'errors',
|
63 |
|
|
);
|
64 |
|
|
foreach ($unset_properties as $property) {
|
65 |
|
|
unset($new_flag[$property]);
|
66 |
|
|
}
|
67 |
|
|
|
68 |
|
|
$output .= $indent . '// Exported flag: "' . check_plain($flag->get_title()) . '"' . ".\n";
|
69 |
|
|
$output .= $indent . '$flags[\'' . $flag->name . '\'] = ' . (function_exists('features_var_export') ? features_var_export($new_flag, $indent) : var_export($new_flag, TRUE)) . ";\n";
|
70 |
|
|
}
|
71 |
|
|
$output .= $indent . 'return $flags;' . "\n";
|
72 |
|
|
return $output;
|
73 |
|
|
}
|
74 |
|
|
|
75 |
|
|
/**
|
76 |
|
|
* Form to import a flag.
|
77 |
|
|
*/
|
78 |
|
|
function flag_import_form() {
|
79 |
|
|
$form = array();
|
80 |
|
|
|
81 |
|
|
$form['import'] = array(
|
82 |
|
|
'#title' => t('Flag import code'),
|
83 |
|
|
'#type' => 'textarea',
|
84 |
|
|
'#default_value' => '',
|
85 |
|
|
'#rows' => 15,
|
86 |
|
|
'#required' => TRUE,
|
87 |
|
|
'#description' => t('Paste the code from a <a href="@export-url">flag export</a> here to import it into you site. Flags imported with the same name will update existing flags. Flags with a new name will be created.', array('@export-url' => url(FLAG_ADMIN_PATH . '/export'))),
|
88 |
|
|
);
|
89 |
|
|
$form['submit'] = array(
|
90 |
|
|
'#value' => t('Import'),
|
91 |
|
|
'#type' => 'submit',
|
92 |
|
|
);
|
93 |
|
|
|
94 |
|
|
return $form;
|
95 |
|
|
}
|
96 |
|
|
|
97 |
|
|
/**
|
98 |
|
|
* Validate handler; Import a flag.
|
99 |
|
|
*/
|
100 |
|
|
function flag_import_form_validate($form, &$form_state) {
|
101 |
|
|
$flags = array();
|
102 |
|
|
ob_start();
|
103 |
|
|
eval($form_state['values']['import']);
|
104 |
|
|
ob_end_clean();
|
105 |
|
|
|
106 |
|
|
if (!isset($flags) || !is_array($flags)) {
|
107 |
|
|
form_set_error('import', t('A valid list of flags could not be found in the import code.'));
|
108 |
|
|
return;
|
109 |
|
|
}
|
110 |
|
|
|
111 |
|
|
// Create the flag object.
|
112 |
|
|
foreach ($flags as $flag_name => $flag_info) {
|
113 |
|
|
// Backward compatibility: old exported flags have their names in $flag_info
|
114 |
|
|
// instead, so we use the += operator to not overwrite it.
|
115 |
|
|
$flag_info += array(
|
116 |
|
|
'name' => $flag_name,
|
117 |
|
|
);
|
118 |
|
|
$new_flag = flag_flag::factory_by_array($flag_info);
|
119 |
|
|
|
120 |
|
|
// Give new flags with the same name a matching FID, which tells Flag to
|
121 |
|
|
// update the existing flag, rather than creating a new one.
|
122 |
|
|
if ($existing_flag = flag_get_flag($new_flag->name)) {
|
123 |
|
|
$new_flag->fid = $existing_flag->fid;
|
124 |
|
|
}
|
125 |
|
|
|
126 |
|
|
if ($errors = $new_flag->validate()) {
|
127 |
|
|
$message = t('The import of the %flag flag failed because the following errors were encountered during the import:', array('%flag' => $new_flag->name));
|
128 |
|
|
$message_errors = array();
|
129 |
|
|
foreach ($errors as $field => $field_errors) {
|
130 |
|
|
foreach ($field_errors as $error) {
|
131 |
|
|
$message_errors[] = $error['message'];
|
132 |
|
|
}
|
133 |
|
|
}
|
134 |
|
|
form_set_error('import', $message . theme('item_list', array('items' => $message_errors)));
|
135 |
|
|
}
|
136 |
|
|
else {
|
137 |
|
|
// Save the new flag for the submit handler.
|
138 |
|
|
$form_state['flags'][] = $new_flag;
|
139 |
|
|
}
|
140 |
|
|
}
|
141 |
|
|
}
|
142 |
|
|
|
143 |
|
|
/**
|
144 |
|
|
* Submit handler; Import a flag.
|
145 |
|
|
*/
|
146 |
|
|
function flag_import_form_submit($form, &$form_state) {
|
147 |
|
|
module_load_include('inc', 'flag', 'includes/flag.admin');
|
148 |
|
|
|
149 |
|
|
// Build up values for the cache clear.
|
150 |
|
|
$entity_types = array();
|
151 |
|
|
$new = FALSE;
|
152 |
|
|
|
153 |
|
|
foreach ($form_state['flags'] as $flag) {
|
154 |
|
|
$flag->save();
|
155 |
|
|
if (!empty($flag->status)) {
|
156 |
|
|
$flag->enable();
|
157 |
|
|
}
|
158 |
|
|
if ($flag->is_new) {
|
159 |
|
|
drupal_set_message(t('Flag @name has been imported.', array('@name' => $flag->name)));
|
160 |
|
|
$new = TRUE;
|
161 |
|
|
}
|
162 |
|
|
else {
|
163 |
|
|
drupal_set_message(t('Flag @name has been updated.', array('@name' => $flag->name)));
|
164 |
|
|
}
|
165 |
|
|
$entity_types[] = $flag->entity_type;
|
166 |
|
|
}
|
167 |
|
|
_flag_clear_cache($entity_types, $new);
|
168 |
|
|
|
169 |
|
|
$form_state['redirect'] = FLAG_ADMIN_PATH;
|
170 |
|
|
}
|
171 |
|
|
|
172 |
|
|
/**
|
173 |
|
|
* Export a flag and display it in a form.
|
174 |
|
|
*/
|
175 |
|
|
function flag_export_form($form, &$form_state, $flag = NULL) {
|
176 |
|
|
// If we were passed a flag, use it as the list of flags to export.
|
177 |
|
|
if ($flag) {
|
178 |
|
|
$flags = array($flag);
|
179 |
|
|
}
|
180 |
|
|
|
181 |
|
|
// Display a list of flags to export.
|
182 |
|
|
if (!isset($flags)) {
|
183 |
|
|
if (isset($form_state['values']['flags'])) {
|
184 |
|
|
$flags = array();
|
185 |
|
|
foreach ($form_state['values']['flags'] as $flag_name) {
|
186 |
|
|
if ($flag_name && $flag = flag_get_flag($flag_name)) {
|
187 |
|
|
$flags[] = $flag;
|
188 |
|
|
}
|
189 |
|
|
}
|
190 |
|
|
}
|
191 |
|
|
else {
|
192 |
|
|
$form['flags'] = array(
|
193 |
|
|
'#type' => 'checkboxes',
|
194 |
|
|
'#title' => t('Flags to export'),
|
195 |
|
|
'#options' => drupal_map_assoc(array_keys(flag_get_flags())),
|
196 |
|
|
'#description' => t('Exporting your flags is useful for moving flags from one site to another, or when including your flag definitions in a module.'),
|
197 |
|
|
);
|
198 |
|
|
$form['submit'] = array(
|
199 |
|
|
'#type' => 'submit',
|
200 |
|
|
'#value' => t('Export'),
|
201 |
|
|
);
|
202 |
|
|
}
|
203 |
|
|
}
|
204 |
|
|
|
205 |
|
|
if (isset($flags)) {
|
206 |
|
|
$code = flag_export_flags($flags);
|
207 |
|
|
|
208 |
|
|
// Link to the Features page if module is present, otherwise link to the
|
209 |
|
|
// Drupal project page.
|
210 |
|
|
$features_link = module_exists('features') ? url('admin/build/features') : url('http://drupal.org/project/features');
|
211 |
|
|
|
212 |
|
|
$form['export'] = array(
|
213 |
|
|
'#type' => 'textarea',
|
214 |
|
|
'#title' => t('Flag exports'),
|
215 |
|
|
'#description' => t('Use the exported code to later <a href="@import-flag">import</a> it. Exports can be included in modules using <a href="http://drupal.org/node/305086#default-flags">hook_flag_default_flags()</a> or using the <a href="@features-url">Features</a> module.', array('@import-flag' => url(FLAG_ADMIN_PATH . '/import'), '@features-url' => $features_link)),
|
216 |
|
|
'#value' => $code,
|
217 |
|
|
'#rows' => 15,
|
218 |
|
|
);
|
219 |
|
|
}
|
220 |
|
|
|
221 |
|
|
return $form;
|
222 |
|
|
}
|
223 |
|
|
|
224 |
|
|
/**
|
225 |
|
|
* Submit handler; Rebuild the export form after the list of flags has been set.
|
226 |
|
|
*/
|
227 |
|
|
function flag_export_form_submit($form, &$form_state) {
|
228 |
|
|
$form_state['rebuild'] = TRUE;
|
229 |
|
|
}
|
230 |
|
|
|
231 |
|
|
/**
|
232 |
|
|
* Page for displaying an upgrade message and export form for Flag 1.x flags.
|
233 |
|
|
*/
|
234 |
|
|
function flag_update_page($flag) {
|
235 |
|
|
if ($flag->is_compatible()) {
|
236 |
|
|
drupal_set_message(t('The flag %name is already up-to-date with the latest Flag API and does not need upgrading.', array('%name' => $flag->name)));
|
237 |
|
|
drupal_goto(FLAG_ADMIN_PATH);
|
238 |
|
|
}
|
239 |
|
|
|
240 |
|
|
drupal_set_message(t('The flag %name is currently using the Flag API version @version, which is not compatible with the current version of Flag. You can upgrade this flag by pasting the below code into <em>@module_flag_default_flags()</em> function in the @module.module file.', array('%name' => $flag->name, '@version' => $flag->api_version, '@module' => $flag->module)), 'warning');
|
241 |
|
|
|
242 |
|
|
flag_update_export($flag);
|
243 |
|
|
|
244 |
|
|
return drupal_get_form('flag_export_form', $flag);
|
245 |
|
|
}
|
246 |
|
|
|
247 |
|
|
/**
|
248 |
|
|
* Update a flag before export.
|
249 |
|
|
*
|
250 |
fd5a8e62
|
Assos Assos
|
* @param flag_flag $flag
|
251 |
85ad3d82
|
Assos Assos
|
* The flag object passed by reference.
|
252 |
|
|
*/
|
253 |
|
|
function flag_update_export(&$flag) {
|
254 |
|
|
// Set the API version to 1 by default: version 1 did not explicitly define
|
255 |
|
|
// the API version.
|
256 |
|
|
if (empty($flag->api_version)) {
|
257 |
|
|
$flag->api_version = 1;
|
258 |
|
|
}
|
259 |
|
|
|
260 |
|
|
// Get all our update classes.
|
261 |
|
|
// This is not terribly graceful, but the alternative is declaring our classes
|
262 |
|
|
// explicitly, or registering them with the Drupal autoloader and then running
|
263 |
|
|
// a database query, which seems a waste of space given we only ever need
|
264 |
|
|
// these here.
|
265 |
|
|
$classes = get_declared_classes();
|
266 |
|
|
$update_handlers = array();
|
267 |
|
|
foreach ($classes as $class) {
|
268 |
|
|
// Any class whose name is of the form 'FlagUpdate_foo' is one of ours, we
|
269 |
|
|
// assume. Should this prove problematic, we can add use of reflection here.
|
270 |
|
|
if (substr($class, 0, 11) == 'FlagUpdate_') {
|
271 |
|
|
// @todo: change this to work with the static class when we drop support
|
272 |
|
|
// for PHP 5.2: see commit d5b517.
|
273 |
76e2e7c3
|
Assos Assos
|
$update_handler = new $class();
|
274 |
85ad3d82
|
Assos Assos
|
// Cast to string, as decimals as array keys seem to be rounded down to
|
275 |
|
|
// ints, WTF PHP?
|
276 |
|
|
$version = (string) $update_handler->old_api_version;
|
277 |
|
|
|
278 |
|
|
$update_handlers[$version] = $update_handler;
|
279 |
|
|
}
|
280 |
|
|
}
|
281 |
|
|
// Sort the classes by old version number.
|
282 |
|
|
uksort($update_handlers, 'version_compare');
|
283 |
|
|
|
284 |
|
|
// Work through each update handler.
|
285 |
|
|
foreach ($update_handlers as $old_api_version => $update_handler) {
|
286 |
|
|
// Skip update classes that are older than our current flag.
|
287 |
|
|
if (version_compare($old_api_version, $flag->api_version, '<')) {
|
288 |
|
|
continue;
|
289 |
|
|
}
|
290 |
|
|
|
291 |
|
|
// Run the update and change the API version on the flag.
|
292 |
|
|
$update_handler->update($flag);
|
293 |
|
|
$flag->api_version = $update_handler->new_api_version;
|
294 |
|
|
}
|
295 |
|
|
}
|
296 |
|
|
|
297 |
|
|
/**
|
298 |
|
|
* Flag update class for API 1 flags -> API 2.
|
299 |
|
|
*
|
300 |
|
|
* The class name after the prefix is immaterial, though we follow the Drupal
|
301 |
|
|
* system update convention whereby the number here is what we update to.
|
302 |
|
|
*/
|
303 |
|
|
class FlagUpdate_2 {
|
304 |
|
|
|
305 |
|
|
/**
|
306 |
|
|
* The API version this class updates a flag from.
|
307 |
|
|
*
|
308 |
|
|
* @todo: Change this to a class constant when we drop support for PHP 5.2.
|
309 |
|
|
*/
|
310 |
|
|
public $old_api_version = 1;
|
311 |
|
|
|
312 |
|
|
/**
|
313 |
|
|
* The API version this class updates a flag to.
|
314 |
|
|
*/
|
315 |
|
|
public $new_api_version = 2;
|
316 |
|
|
|
317 |
|
|
/**
|
318 |
|
|
* The update function for the flag.
|
319 |
|
|
*/
|
320 |
|
|
static function update(&$flag) {
|
321 |
|
|
if (isset($flag->roles) && !isset($flag->roles['flag'])) {
|
322 |
|
|
$flag->roles = array(
|
323 |
|
|
'flag' => $flag->roles,
|
324 |
|
|
'unflag' => $flag->roles,
|
325 |
|
|
);
|
326 |
|
|
}
|
327 |
|
|
}
|
328 |
|
|
}
|
329 |
|
|
|
330 |
|
|
/**
|
331 |
|
|
* Flag update class for API 2 flags -> API 3.
|
332 |
|
|
*/
|
333 |
|
|
class FlagUpdate_3 {
|
334 |
|
|
|
335 |
|
|
public $old_api_version = 2;
|
336 |
|
|
public $new_api_version = 3;
|
337 |
|
|
|
338 |
|
|
static function update(&$flag) {
|
339 |
|
|
// Change the content_type property to entity_type.
|
340 |
|
|
if (isset($flag->content_type)) {
|
341 |
|
|
$flag->entity_type = $flag->content_type;
|
342 |
|
|
unset($flag->content_type);
|
343 |
|
|
}
|
344 |
|
|
|
345 |
|
|
// We can't convert the flag roles data to user permissions at this point
|
346 |
|
|
// because the flag is disabled and hence hook_permission() doesn't see it
|
347 |
|
|
// to define its permissions.
|
348 |
|
|
// Instead, we copy it to import_roles, which the flag add form will handle
|
349 |
|
|
// on new flags (which this flag will behave as when it is re-enabled).
|
350 |
|
|
// @see flag_form()
|
351 |
|
|
if (isset($flag->roles)) {
|
352 |
|
|
$flag->import_roles = $flag->roles;
|
353 |
|
|
}
|
354 |
|
|
|
355 |
|
|
// Update show_on_teaser property to use new view mode settings.
|
356 |
|
|
if (!empty($flag->show_on_teaser)) {
|
357 |
|
|
$flag->show_in_links['teaser'] = TRUE;
|
358 |
|
|
unset($flag->show_on_teaser);
|
359 |
|
|
}
|
360 |
|
|
|
361 |
|
|
// Update show_on_page property to use new view mode settings.
|
362 |
|
|
if (!empty($flag->show_on_page)) {
|
363 |
|
|
$flag->show_in_links['full'] = TRUE;
|
364 |
|
|
unset($flag->show_on_page);
|
365 |
|
|
}
|
366 |
|
|
|
367 |
|
|
// Update show_on_comment and show_on_entity properties to use new view
|
368 |
76e2e7c3
|
Assos Assos
|
// mode settings. Since the old logic was to show on all view modes, do
|
369 |
|
|
// that.
|
370 |
85ad3d82
|
Assos Assos
|
if (!empty($flag->show_on_entity) || !empty($flag->show_on_comment)) {
|
371 |
|
|
if ($entity_info = entity_get_info($flag->entity_type)) {
|
372 |
|
|
foreach ($entity_info['view modes'] as $view_mode => $value) {
|
373 |
|
|
$flag->show_in_links[$view_mode] = TRUE;
|
374 |
|
|
}
|
375 |
|
|
}
|
376 |
|
|
|
377 |
|
|
unset($flag->show_on_entity, $flag->show_on_comment);
|
378 |
|
|
}
|
379 |
|
|
}
|
380 |
|
|
} |