Mercurial > hg > drupalISMI
comparison relation_processor/FeedsRelationProcessor.inc @ 0:124ef8f3b22d
initial
author | Dirk Wintergruen <dwinter@mpiwg-berlin.mpg.de> |
---|---|
date | Fri, 27 Mar 2015 19:21:42 +0100 |
parents | |
children | 1c73c660c2f2 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:124ef8f3b22d |
---|---|
1 <?php | |
2 | |
3 /** | |
4 * @file | |
5 * Class definition of FeedsNodeProcessor. | |
6 */ | |
7 | |
8 /** | |
9 * Creates nodes from feed items. | |
10 */ | |
11 class FeedsRelationProcessor extends FeedsProcessor { | |
12 | |
13 /** | |
14 * Define entity type. | |
15 */ | |
16 public function entityType() { | |
17 return 'relation'; | |
18 } | |
19 | |
20 /** | |
21 * Implements parent::entityInfo(). | |
22 */ | |
23 protected function entityInfo() { | |
24 $info = parent::entityInfo(); | |
25 $info['label plural'] = t('Relations'); | |
26 return $info; | |
27 } | |
28 | |
29 /** | |
30 * Creates a new node in memory and returns it. | |
31 */ | |
32 protected function newEntity(FeedsSource $source) { | |
33 /*$node = new stdClass(); | |
34 $node->type = $this->bundle(); | |
35 $node->changed = REQUEST_TIME; | |
36 $node->created = REQUEST_TIME; | |
37 $node->language = LANGUAGE_NONE; | |
38 $node->is_new = TRUE; | |
39 node_object_prepare($node); | |
40 // Populate properties that are set by node_object_prepare(). | |
41 $node->log = 'Created by FeedsNodeProcessor'; | |
42 $node->uid = $this->config['author']; | |
43 */ | |
44 | |
45 | |
46 $relation = new stdClass(); | |
47 $relation->is_new = TRUE; | |
48 | |
49 $relation->relation_type = $this->bundle(); | |
50 $relation->uid = $this->config['author']; | |
51 $relation->endpoints[LANGUAGE_NONE] = Null; | |
52 | |
53 $relation->changed = REQUEST_TIME; | |
54 $relation->created = REQUEST_TIME; | |
55 | |
56 return $relation; | |
57 | |
58 } | |
59 | |
60 /** | |
61 * Loads an existing node. | |
62 * | |
63 * If the update existing method is not FEEDS_UPDATE_EXISTING, only the node | |
64 * table will be loaded, foregoing the node_load API for better performance. | |
65 * | |
66 * @todo Reevaluate the use of node_object_prepare(). | |
67 */ | |
68 protected function entityLoad(FeedsSource $source, $nid) { | |
69 | |
70 $node = relation_load($nid); | |
71 | |
72 if ($this->config['update_existing'] != FEEDS_UPDATE_EXISTING) { | |
73 $node->uid = $this->config['author']; | |
74 } | |
75 | |
76 /* node_object_prepare($node); | |
77 | |
78 // Workaround for issue #1247506. See #1245094 for backstory. | |
79 if (!empty($node->menu)) { | |
80 // If the node has a menu item(with a valid mlid) it must be flagged | |
81 // 'enabled'. | |
82 $node->menu['enabled'] = (int) (bool) $node->menu['mlid']; | |
83 } | |
84 */ | |
85 // Populate properties that are set by node_object_prepare(). | |
86 if ($this->config['update_existing'] == FEEDS_UPDATE_EXISTING) { | |
87 $node->log = 'Updated by FeedsNodeProcessor'; | |
88 } | |
89 else { | |
90 $node->log = 'Replaced by FeedsNodeProcessor'; | |
91 } | |
92 return $node; | |
93 } | |
94 | |
95 /** | |
96 * Check that the user has permission to save a node. | |
97 */ | |
98 protected function entitySaveAccess($entity) { | |
99 | |
100 // The check will be skipped for anonymous nodes. | |
101 if ($this->config['authorize'] && !empty($entity->uid)) { | |
102 | |
103 $author = user_load($entity->uid); | |
104 | |
105 // If the uid was mapped directly, rather than by email or username, it | |
106 // could be invalid. | |
107 if (!$author) { | |
108 $message = 'User %uid is not a valid user.'; | |
109 throw new FeedsAccessException(t($message, array('%uid' => $entity->uid))); | |
110 } | |
111 | |
112 if (empty($entity->nid) || !empty($entity->is_new)) { | |
113 $op = 'create'; | |
114 $access = node_access($op, $entity->type, $author); | |
115 } | |
116 else { | |
117 $op = 'update'; | |
118 $access = node_access($op, $entity, $author); | |
119 } | |
120 | |
121 if (!$access) { | |
122 $message = 'User %name is not authorized to %op content type %content_type.'; | |
123 throw new FeedsAccessException(t($message, array('%name' => $author->name, '%op' => $op, '%content_type' => $entity->type))); | |
124 } | |
125 } | |
126 } | |
127 | |
128 /** | |
129 * Validates a node. | |
130 */ | |
131 protected function entityValidate($entity) { | |
132 if (!isset($entity->uid) || !is_numeric($entity->uid)) { | |
133 $entity->uid = $this->config['author']; | |
134 } | |
135 } | |
136 /** | |
137 * Save a node. | |
138 */ | |
139 public function entitySave($entity) { | |
140 relation_save($entity); | |
141 } | |
142 | |
143 /** | |
144 * Delete a series of nodes. | |
145 */ | |
146 protected function entityDeleteMultiple($nids) { | |
147 relation_delete_multiple($nids); | |
148 } | |
149 | |
150 /** | |
151 * Implement expire(). | |
152 * | |
153 * @todo: move to processor stage? | |
154 */ | |
155 public function expire($time = NULL) { | |
156 if ($time === NULL) { | |
157 $time = $this->expiryTime(); | |
158 } | |
159 if ($time == FEEDS_EXPIRE_NEVER) { | |
160 return; | |
161 } | |
162 $count = $this->getLimit(); | |
163 $nodes = db_query_range("SELECT n.nid FROM {node} n JOIN {feeds_item} fi ON fi.entity_type = 'node' AND n.nid = fi.entity_id WHERE fi.id = :id AND n.created < :created", 0, $count, array(':id' => $this->id, ':created' => REQUEST_TIME - $time)); | |
164 $nids = array(); | |
165 foreach ($nodes as $node) { | |
166 $nids[$node->nid] = $node->nid; | |
167 } | |
168 $this->entityDeleteMultiple($nids); | |
169 if (db_query_range("SELECT 1 FROM {node} n JOIN {feeds_item} fi ON fi.entity_type = 'node' AND n.nid = fi.entity_id WHERE fi.id = :id AND n.created < :created", 0, 1, array(':id' => $this->id, ':created' => REQUEST_TIME - $time))->fetchField()) { | |
170 return FEEDS_BATCH_ACTIVE; | |
171 } | |
172 return FEEDS_BATCH_COMPLETE; | |
173 } | |
174 | |
175 /** | |
176 * Return expiry time. | |
177 */ | |
178 public function expiryTime() { | |
179 return $this->config['expire']; | |
180 } | |
181 | |
182 /** | |
183 * Override parent::configDefaults(). | |
184 */ | |
185 public function configDefaults() { | |
186 return array( | |
187 'expire' => FEEDS_EXPIRE_NEVER, | |
188 'author' => 0, | |
189 'authorize' => TRUE, | |
190 ) + parent::configDefaults(); | |
191 } | |
192 | |
193 /** | |
194 * Override parent::configForm(). | |
195 */ | |
196 public function configForm(&$form_state) { | |
197 $form = parent::configForm($form_state); | |
198 | |
199 $author = user_load($this->config['author']); | |
200 $form['author'] = array( | |
201 '#type' => 'textfield', | |
202 '#title' => t('Author'), | |
203 '#description' => t('Select the author of the nodes to be created - leave empty to assign "anonymous".'), | |
204 '#autocomplete_path' => 'user/autocomplete', | |
205 '#default_value' => empty($author->name) ? 'anonymous' : check_plain($author->name), | |
206 ); | |
207 $form['authorize'] = array( | |
208 '#type' => 'checkbox', | |
209 '#title' => t('Authorize'), | |
210 '#description' => t('Check that the author has permission to create the node.'), | |
211 '#default_value' => $this->config['authorize'], | |
212 ); | |
213 $period = drupal_map_assoc(array(FEEDS_EXPIRE_NEVER, 3600, 10800, 21600, 43200, 86400, 259200, 604800, 2592000, 2592000 * 3, 2592000 * 6, 31536000), 'feeds_format_expire'); | |
214 $form['expire'] = array( | |
215 '#type' => 'select', | |
216 '#title' => t('Expire nodes'), | |
217 '#options' => $period, | |
218 '#description' => t('Select after how much time nodes should be deleted. The node\'s published date will be used for determining the node\'s age, see Mapping settings.'), | |
219 '#default_value' => $this->config['expire'], | |
220 ); | |
221 return $form; | |
222 } | |
223 | |
224 /** | |
225 * Override parent::configFormValidate(). | |
226 */ | |
227 public function configFormValidate(&$values) { | |
228 if ($author = user_load_by_name($values['author'])) { | |
229 $values['author'] = $author->uid; | |
230 } | |
231 else { | |
232 $values['author'] = 0; | |
233 } | |
234 } | |
235 | |
236 /** | |
237 * Reschedule if expiry time changes. | |
238 */ | |
239 public function configFormSubmit(&$values) { | |
240 if ($this->config['expire'] != $values['expire']) { | |
241 feeds_reschedule($this->id); | |
242 } | |
243 parent::configFormSubmit($values); | |
244 } | |
245 | |
246 /** | |
247 * Override setTargetElement to operate on a target item that is a node. | |
248 */ | |
249 public function setTargetElement(FeedsSource $source, $target_node, $target_element, $value) { | |
250 switch ($target_element) { | |
251 case 'created': | |
252 $target_node->created = feeds_to_unixtime($value, REQUEST_TIME); | |
253 break; | |
254 case 'feeds_source': | |
255 // Get the class of the feed node importer's fetcher and set the source | |
256 // property. See feeds_node_update() how $node->feeds gets stored. | |
257 if ($id = feeds_get_importer_id($this->bundle())) { | |
258 $class = get_class(feeds_importer($id)->fetcher); | |
259 $target_node->feeds[$class]['source'] = $value; | |
260 // This effectively suppresses 'import on submission' feature. | |
261 // See feeds_node_insert(). | |
262 $target_node->feeds['suppress_import'] = TRUE; | |
263 } | |
264 break; | |
265 case 'user_name': | |
266 if ($user = user_load_by_name($value)) { | |
267 $target_node->uid = $user->uid; | |
268 } | |
269 break; | |
270 case 'user_mail': | |
271 if ($user = user_load_by_mail($value)) { | |
272 $target_node->uid = $user->uid; | |
273 } | |
274 break; | |
275 default: | |
276 parent::setTargetElement($source, $target_node, $target_element, $value); | |
277 break; | |
278 } | |
279 } | |
280 | |
281 /** | |
282 * Return available mapping targets. | |
283 */ | |
284 public function getMappingTargets() { | |
285 $type = relation_type_load($this->bundle()); | |
286 | |
287 $targets = parent::getMappingTargets(); | |
288 | |
289 $targets['source_id'] = array( | |
290 'name' => t('Source Field'), | |
291 'description' => t('Source.'), | |
292 'optional_unique' => FALSE, | |
293 ); | |
294 | |
295 $targets['target_id'] = array( | |
296 'name' => t('Target Field'), | |
297 'description' => t('Target.'), | |
298 'optional_unique' => FALSE, | |
299 ); | |
300 | |
301 | |
302 $targets['relation_name'] = array( | |
303 'name' => t('Relation type'), | |
304 'description' => t('Target.'), | |
305 'optional_unique' => FALSE, | |
306 ); | |
307 | |
308 | |
309 $targets['nid'] = array( | |
310 'name' => t('Node ID'), | |
311 'description' => t('The nid of the node. NOTE: use this feature with care, node ids are usually assigned by Drupal.'), | |
312 'optional_unique' => TRUE, | |
313 ); | |
314 $targets['uid'] = array( | |
315 'name' => t('User ID'), | |
316 'description' => t('The Drupal user ID of the node author.'), | |
317 ); | |
318 $targets['user_name'] = array( | |
319 'name' => t('Username'), | |
320 'description' => t('The Drupal username of the node author.'), | |
321 ); | |
322 $targets['user_mail'] = array( | |
323 'name' => t('User email'), | |
324 'description' => t('The email address of the node author.'), | |
325 ); | |
326 $targets['status'] = array( | |
327 'name' => t('Published status'), | |
328 'description' => t('Whether a node is published or not. 1 stands for published, 0 for not published.'), | |
329 ); | |
330 $targets['created'] = array( | |
331 'name' => t('Published date'), | |
332 'description' => t('The UNIX time when a node has been published.'), | |
333 ); | |
334 | |
335 // Include language field if Locale module is enabled. | |
336 if (module_exists('locale')) { | |
337 $targets['language'] = array( | |
338 'name' => t('Language'), | |
339 'description' => t('The two-character language code of the node.'), | |
340 ); | |
341 } | |
342 | |
343 | |
344 // If the target content type is a Feed node, expose its source field. | |
345 if ($id = feeds_get_importer_id($this->bundle())) { | |
346 $name = feeds_importer($id)->config['name']; | |
347 $targets['feeds_source'] = array( | |
348 'name' => t('Feed source'), | |
349 'description' => t('The content type created by this processor is a Feed Node, it represents a source itself. Depending on the fetcher selected on the importer "@importer", this field is expected to be for example a URL or a path to a file.', array('@importer' => $name)), | |
350 'optional_unique' => TRUE, | |
351 ); | |
352 } | |
353 | |
354 // Let other modules expose mapping targets. | |
355 self::loadMappers(); | |
356 | |
357 // load nodes mapper | |
358 require_once("nodes.inc"); | |
359 //$entity_type = $this->entityType(); | |
360 $entity_type = "relation"; | |
361 $bundle = $this->bundle(); | |
362 drupal_alter('feeds_processor_targets', $targets, $entity_type, $bundle); | |
363 | |
364 return $targets; | |
365 } | |
366 | |
367 /** | |
368 * Get nid of an existing feed item node if available. | |
369 */ | |
370 protected function existingEntityId(FeedsSource $source, FeedsParserResult $result) { | |
371 if ($nid = parent::existingEntityId($source, $result)) { | |
372 return $nid; | |
373 } | |
374 | |
375 // Iterate through all unique targets and test whether they do already | |
376 // exist in the database. | |
377 foreach ($this->uniqueTargets($source, $result) as $target => $value) { | |
378 switch ($target) { | |
379 case 'nid': | |
380 $nid = db_query("SELECT rid FROM {relation} WHERE rid = :rid", array(':rid' => $value))->fetchField(); | |
381 break; | |
382 case 'title': | |
383 $nid = db_query("SELECT rid FROM {relation} WHERE title = :title AND type = :type", array(':title' => $value, ':type' => $this->bundle()))->fetchField(); | |
384 break; | |
385 case 'feeds_source': | |
386 if ($id = feeds_get_importer_id($this->bundle())) { | |
387 $nid = db_query("SELECT fs.feed_nid FROM {relation} n JOIN {feeds_source} fs ON n.rid = fs.feed_nid WHERE fs.id = :id AND fs.source = :source", array(':id' => $id, ':source' => $value))->fetchField(); | |
388 } | |
389 break; | |
390 } | |
391 if ($nid) { | |
392 // Return with the first nid found. | |
393 return $nid; | |
394 } | |
395 } | |
396 return 0; | |
397 } | |
398 | |
399 | |
400 /** | |
401 * Provides a list of bundle options for use in select lists. | |
402 * | |
403 * @return array | |
404 * A keyed array of bundle => label. | |
405 */ | |
406 public function bundleOptions() { | |
407 $options = array(); | |
408 | |
409 $options = relation_get_types_options(); | |
410 return $options; | |
411 | |
412 } | |
413 } |