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 dpm($this->bundle()); | |
| 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 } |
