d20545f2e27cfb17151f630a3219568f8145ab44
[yaffs-website] / web / core / modules / node / src / Plugin / migrate / source / d6 / Node.php
1 <?php
2
3 namespace Drupal\node\Plugin\migrate\source\d6;
4
5 use Drupal\Core\Database\Query\SelectInterface;
6 use Drupal\Core\Entity\EntityManagerInterface;
7 use Drupal\Core\Extension\ModuleHandler;
8 use Drupal\Core\State\StateInterface;
9 use Drupal\migrate\Plugin\MigrationInterface;
10 use Drupal\migrate\Row;
11 use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase;
12 use Symfony\Component\DependencyInjection\ContainerInterface;
13
14 /**
15  * Drupal 6 node source from database.
16  *
17  * @MigrateSource(
18  *   id = "d6_node",
19  *   source_module = "node"
20  *
21  * )
22  */
23 class Node extends DrupalSqlBase {
24
25   /**
26    * The join options between the node and the node_revisions table.
27    */
28   const JOIN = 'n.vid = nr.vid';
29
30   /**
31    * The default filter format.
32    *
33    * @var string
34    */
35   protected $filterDefaultFormat;
36
37   /**
38    * Cached field and field instance definitions.
39    *
40    * @var array
41    */
42   protected $fieldInfo;
43
44   /**
45    * The module handler.
46    *
47    * @var \Drupal\Core\Extension\ModuleHandler
48    */
49   protected $moduleHandler;
50
51   /**
52    * {@inheritdoc}
53    */
54   public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, StateInterface $state, EntityManagerInterface $entity_manager, ModuleHandler $module_handler) {
55     parent::__construct($configuration, $plugin_id, $plugin_definition, $migration, $state, $entity_manager);
56     $this->moduleHandler = $module_handler;
57   }
58
59   /**
60    * {@inheritdoc}
61    */
62   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
63     return new static(
64       $configuration,
65       $plugin_id,
66       $plugin_definition,
67       $migration,
68       $container->get('state'),
69       $container->get('entity.manager'),
70       $container->get('module_handler')
71     );
72   }
73
74   /**
75    * {@inheritdoc}
76    */
77   public function query() {
78     $query = $this->select('node_revisions', 'nr');
79     $query->innerJoin('node', 'n', static::JOIN);
80     $this->handleTranslations($query);
81
82     $query->fields('n', [
83         'nid',
84         'type',
85         'language',
86         'status',
87         'created',
88         'changed',
89         'comment',
90         'promote',
91         'moderate',
92         'sticky',
93         'tnid',
94         'translate',
95       ])
96       ->fields('nr', [
97         'title',
98         'body',
99         'teaser',
100         'log',
101         'timestamp',
102         'format',
103         'vid',
104       ]);
105     $query->addField('n', 'uid', 'node_uid');
106     $query->addField('nr', 'uid', 'revision_uid');
107
108     // If the content_translation module is enabled, get the source langcode
109     // to fill the content_translation_source field.
110     if ($this->moduleHandler->moduleExists('content_translation')) {
111       $query->leftJoin('node', 'nt', 'n.tnid = nt.nid');
112       $query->addField('nt', 'language', 'source_langcode');
113     }
114
115     if (isset($this->configuration['node_type'])) {
116       $query->condition('n.type', $this->configuration['node_type']);
117     }
118
119     return $query;
120   }
121
122   /**
123    * {@inheritdoc}
124    */
125   protected function initializeIterator() {
126     $this->filterDefaultFormat = $this->variableGet('filter_default_format', '1');
127     return parent::initializeIterator();
128   }
129
130   /**
131    * {@inheritdoc}
132    */
133   public function fields() {
134     $fields = [
135       'nid' => $this->t('Node ID'),
136       'type' => $this->t('Type'),
137       'title' => $this->t('Title'),
138       'body' => $this->t('Body'),
139       'format' => $this->t('Format'),
140       'teaser' => $this->t('Teaser'),
141       'node_uid' => $this->t('Node authored by (uid)'),
142       'revision_uid' => $this->t('Revision authored by (uid)'),
143       'created' => $this->t('Created timestamp'),
144       'changed' => $this->t('Modified timestamp'),
145       'status' => $this->t('Published'),
146       'promote' => $this->t('Promoted to front page'),
147       'sticky' => $this->t('Sticky at top of lists'),
148       'revision' => $this->t('Create new revision'),
149       'language' => $this->t('Language (fr, en, ...)'),
150       'tnid' => $this->t('The translation set id for this node'),
151       'timestamp' => $this->t('The timestamp the latest revision of this node was created.'),
152     ];
153     return $fields;
154   }
155
156   /**
157    * {@inheritdoc}
158    */
159   public function prepareRow(Row $row) {
160     // format = 0 can happen when the body field is hidden. Set the format to 1
161     // to avoid migration map issues (since the body field isn't used anyway).
162     if ($row->getSourceProperty('format') === '0') {
163       $row->setSourceProperty('format', $this->filterDefaultFormat);
164     }
165
166     if ($this->moduleExists('content') && $this->getModuleSchemaVersion('content') >= 6001) {
167       foreach ($this->getFieldValues($row) as $field => $values) {
168         $row->setSourceProperty($field, $values);
169       }
170     }
171
172     // Make sure we always have a translation set.
173     if ($row->getSourceProperty('tnid') == 0) {
174       $row->setSourceProperty('tnid', $row->getSourceProperty('nid'));
175     }
176
177     return parent::prepareRow($row);
178   }
179
180   /**
181    * Gets field values for a node.
182    *
183    * @param \Drupal\migrate\Row $node
184    *   The node.
185    *
186    * @return array
187    *   Field values, keyed by field name.
188    */
189   protected function getFieldValues(Row $node) {
190     $values = [];
191     foreach ($this->getFieldInfo($node->getSourceProperty('type')) as $field => $info) {
192       $values[$field] = $this->getFieldData($info, $node);
193     }
194     return $values;
195   }
196
197   /**
198    * Gets field and instance definitions from the database.
199    *
200    * @param string $node_type
201    *   The node type for which to get field info.
202    *
203    * @return array
204    *   Field and instance information for the node type, keyed by field name.
205    */
206   protected function getFieldInfo($node_type) {
207     if (!isset($this->fieldInfo)) {
208       $this->fieldInfo = [];
209
210       // Query the database directly for all field info.
211       $query = $this->select('content_node_field_instance', 'cnfi');
212       $query->join('content_node_field', 'cnf', 'cnf.field_name = cnfi.field_name');
213       $query->fields('cnfi');
214       $query->fields('cnf');
215
216       foreach ($query->execute() as $field) {
217         $this->fieldInfo[$field['type_name']][$field['field_name']] = $field;
218       }
219
220       foreach ($this->fieldInfo as $type => $fields) {
221         foreach ($fields as $field => $info) {
222           foreach ($info as $property => $value) {
223             if ($property == 'db_columns' || preg_match('/_settings$/', $property)) {
224               $this->fieldInfo[$type][$field][$property] = unserialize($value);
225             }
226           }
227         }
228       }
229     }
230
231     return isset($this->fieldInfo[$node_type]) ? $this->fieldInfo[$node_type] : [];
232   }
233
234   /**
235    * Retrieves raw field data for a node.
236    *
237    * @param array $field
238    *   A field and instance definition from getFieldInfo().
239    * @param \Drupal\migrate\Row $node
240    *   The node.
241    *
242    * @return array
243    *   The field values, keyed by delta.
244    */
245   protected function getFieldData(array $field, Row $node) {
246     $field_table = 'content_' . $field['field_name'];
247     $node_table = 'content_type_' . $node->getSourceProperty('type');
248
249     /** @var \Drupal\Core\Database\Schema $db */
250     $db = $this->getDatabase()->schema();
251
252     if ($db->tableExists($field_table)) {
253       $query = $this->select($field_table, 't');
254
255       // If the delta column does not exist, add it as an expression to
256       // normalize the query results.
257       if ($db->fieldExists($field_table, 'delta')) {
258         $query->addField('t', 'delta');
259       }
260       else {
261         $query->addExpression(0, 'delta');
262       }
263     }
264     elseif ($db->tableExists($node_table)) {
265       $query = $this->select($node_table, 't');
266
267       // Every row should have a delta of 0.
268       $query->addExpression(0, 'delta');
269     }
270
271     if (isset($query)) {
272       $columns = array_keys($field['db_columns']);
273
274       // Add every column in the field's schema.
275       foreach ($columns as $column) {
276         $query->addField('t', $field['field_name'] . '_' . $column, $column);
277       }
278
279       return $query
280         // This call to isNotNull() is a kludge which relies on the convention
281         // that field schemas usually define their most important column first.
282         // A better way would be to allow field plugins to alter the query
283         // directly before it's run, but this will do for the time being.
284         ->isNotNull($field['field_name'] . '_' . $columns[0])
285         ->condition('nid', $node->getSourceProperty('nid'))
286         ->condition('vid', $node->getSourceProperty('vid'))
287         ->execute()
288         ->fetchAllAssoc('delta');
289     }
290     else {
291       return [];
292     }
293   }
294
295   /**
296    * Retrieves raw field data for a node.
297    *
298    * @deprecated in Drupal 8.2.x, to be removed in Drupal 9.0.x. Use
299    *   getFieldData() instead.
300    *
301    * @param array $field
302    *   A field and instance definition from getFieldInfo().
303    * @param \Drupal\migrate\Row $node
304    *   The node.
305    *
306    * @return array
307    *   The field values, keyed by delta.
308    */
309   protected function getCckData(array $field, Row $node) {
310     return $this->getFieldData($field, $node);
311   }
312
313   /**
314    * {@inheritdoc}
315    */
316   public function getIds() {
317     $ids['nid']['type'] = 'integer';
318     $ids['nid']['alias'] = 'n';
319     return $ids;
320   }
321
322   /**
323    * Adapt our query for translations.
324    *
325    * @param \Drupal\Core\Database\Query\SelectInterface $query
326    *   The generated query.
327    */
328   protected function handleTranslations(SelectInterface $query) {
329     // Check whether or not we want translations.
330     if (empty($this->configuration['translations'])) {
331       // No translations: Yield untranslated nodes, or default translations.
332       $query->where('n.tnid = 0 OR n.tnid = n.nid');
333     }
334     else {
335       // Translations: Yield only non-default translations.
336       $query->where('n.tnid <> 0 AND n.tnid <> n.nid');
337     }
338   }
339
340 }