1 |
7295e063
|
Assos Assos
|
<?php
|
2 |
|
|
|
3 |
|
|
/**
|
4 |
|
|
* @file
|
5 |
|
|
* Drush commands for Feeds module.
|
6 |
|
|
*/
|
7 |
|
|
|
8 |
|
|
/**
|
9 |
|
|
* The default maximum number of feeds to list or import.
|
10 |
|
|
*
|
11 |
|
|
* @var int
|
12 |
|
|
*/
|
13 |
|
|
define('DRUSH_FEEDS_DEFAULT_LIMIT', 2147483647);
|
14 |
|
|
|
15 |
|
|
/**
|
16 |
|
|
* Implements hook_drush_command().
|
17 |
|
|
*/
|
18 |
|
|
function feeds_drush_command() {
|
19 |
|
|
$items = array();
|
20 |
|
|
|
21 |
|
|
$items['feeds-list-importers'] = array(
|
22 |
|
|
'description' => 'Get a list of all Feeds importers in the system.',
|
23 |
|
|
'aliases' => array('feeds'),
|
24 |
|
|
);
|
25 |
|
|
|
26 |
|
|
$items['feeds-list-feeds'] = array(
|
27 |
|
|
'description' => 'List all feed sources.',
|
28 |
|
|
'arguments' => array(
|
29 |
|
|
'importer' => 'The name of the Feeds importer whose instances will be listed. Optional.',
|
30 |
|
|
),
|
31 |
|
|
'examples' => array(
|
32 |
|
|
'drush feeds-list-feeds' => 'List all instances of all feeds.',
|
33 |
|
|
'drush feeds-list-feeds rss_feed' => 'List all feed sources of the rss_feed importer.',
|
34 |
|
|
'drush feeds-list-feeds --limit=3' => 'Only list the first three feed sources.',
|
35 |
|
|
),
|
36 |
|
|
'options' => array(
|
37 |
|
|
'limit' => 'Limit the number of feeds to show in the list. Optional.',
|
38 |
|
|
),
|
39 |
|
|
'aliases' => array('feeds-lf'),
|
40 |
|
|
);
|
41 |
|
|
|
42 |
|
|
$items['feeds-import'] = array(
|
43 |
|
|
'description' => 'Imports a feed.',
|
44 |
|
|
'arguments' => array(
|
45 |
|
|
'importer' => 'The name of the Feeds importer that will be refreshed. Mandatory.',
|
46 |
|
|
),
|
47 |
|
|
'options' => array(
|
48 |
|
|
'nid' => '(optional) The nid of the Feeds importer that will be imported.',
|
49 |
|
|
'file' => '(optional) The file to import. Bypasses the configured fetcher and does *not* update the source configuration.',
|
50 |
|
|
'url' => '(optional) The URL to import. Bypasses the configured fetcher and does *not* update the source configuration.',
|
51 |
|
|
'stdin' => '(optional) Read the file to import from stdin. Bypasses the configured fetcher and does *not* update the source configuration.',
|
52 |
|
|
),
|
53 |
|
|
'examples' => array(
|
54 |
|
|
'drush feeds-import my_importer' => "Import items with the importer 'my_importer'.",
|
55 |
|
|
'drush feeds-import my_importer --nid=2' => "Import items with the importer 'my_importer' for feed node 2.",
|
56 |
|
|
),
|
57 |
|
|
'aliases' => array('feeds-im'),
|
58 |
|
|
);
|
59 |
|
|
|
60 |
|
|
$items['feeds-import-all'] = array(
|
61 |
|
|
'description' => 'Import all instances of feeds of the given type.',
|
62 |
|
|
'arguments' => array(
|
63 |
|
|
'importer' => 'The name of the Feeds importer that will be refreshed. Omitting the importer will cause all instances of all feeds to be imported.',
|
64 |
|
|
),
|
65 |
|
|
'examples' => array(
|
66 |
|
|
'drush feeds-import-all' => 'Import all instances of all feeds.',
|
67 |
|
|
'drush feeds-import-all my_importer' => "Import all instances of the importer 'my_importer'.",
|
68 |
|
|
'drush feeds-import-all my_importer --limit=10' => "Import 10 instances of the feed 'my_importer'.",
|
69 |
|
|
),
|
70 |
|
|
'options' => array(
|
71 |
|
|
'limit' => 'Limit the number of feeds to import. Optional.',
|
72 |
|
|
),
|
73 |
|
|
'aliases' => array('feeds-ia', 'feeds-im-all'),
|
74 |
|
|
);
|
75 |
|
|
|
76 |
|
|
$items['feeds-clear'] = array(
|
77 |
|
|
'description' => 'Delete all items from a feed.',
|
78 |
|
|
'arguments' => array(
|
79 |
|
|
'importer' => 'The name of the Feeds importer that will be cleared. Mandatory.',
|
80 |
|
|
),
|
81 |
|
|
'options' => array(
|
82 |
|
|
'nid' => 'The ID of the Feed node that will be cleared. Required if the importer is attached to a content type.',
|
83 |
|
|
),
|
84 |
|
|
'examples' => array(
|
85 |
|
|
'drush feeds-clear my_importer' => "Deletes all items imported with the importer 'my_importer'. The importer must use the standalone import form.",
|
86 |
|
|
'drush feeds-clear my_importer --nid=2' => "Deletes all items imported with the importer 'my_importer' for the feed node with ID 2. The importer must be attached to a content type.",
|
87 |
|
|
),
|
88 |
|
|
);
|
89 |
|
|
|
90 |
|
|
$items['feeds-enable'] = array(
|
91 |
|
|
'description' => 'Enables one or more Feeds importers.',
|
92 |
|
|
'arguments' => array(
|
93 |
|
|
'importers' => 'A space delimited list of Feeds importers. Mandatory.',
|
94 |
|
|
),
|
95 |
|
|
'examples' => array(
|
96 |
|
|
'drush feeds-enable importer_1 importer_2' => "Enable Feeds importers 'importer_1' and 'importer_2'.",
|
97 |
|
|
),
|
98 |
|
|
'aliases' => array('feeds-en'),
|
99 |
|
|
);
|
100 |
|
|
|
101 |
|
|
$items['feeds-disable'] = array(
|
102 |
|
|
'description' => 'Disable one or more Feeds importers.',
|
103 |
|
|
'arguments' => array(
|
104 |
|
|
'importers' => 'A space delimited list of Feeds importers. Mandatory.',
|
105 |
|
|
),
|
106 |
|
|
'examples' => array(
|
107 |
|
|
'drush feeds-disable importer_1 importer_2' => "Disable Feeds importers 'importer_1' and 'importer_2'.",
|
108 |
|
|
),
|
109 |
|
|
'aliases' => array('feeds-dis'),
|
110 |
|
|
);
|
111 |
|
|
|
112 |
|
|
$items['feeds-delete'] = array(
|
113 |
|
|
'description' => 'Deletes one or more Feeds importers.',
|
114 |
|
|
'arguments' => array(
|
115 |
|
|
'importers' => 'A space delimited list of Feeds importers. Mandatory.',
|
116 |
|
|
),
|
117 |
|
|
'examples' => array(
|
118 |
|
|
'drush feeds-delete importer_1 importer_2' => "Delete Feeds importers 'importer_1' and 'importer_2'.",
|
119 |
|
|
),
|
120 |
|
|
);
|
121 |
|
|
|
122 |
|
|
$items['feeds-revert'] = array(
|
123 |
|
|
'description' => 'Reverts one or more Feeds importers.',
|
124 |
|
|
'arguments' => array(
|
125 |
|
|
'importers' => 'A space delimited list of Feeds importers. Mandatory.',
|
126 |
|
|
),
|
127 |
|
|
'examples' => array(
|
128 |
|
|
'drush feeds-revert importer_1 importer_2' => "Revert Feeds importers 'importer_1' and 'importer_2'.",
|
129 |
|
|
),
|
130 |
|
|
);
|
131 |
|
|
|
132 |
|
|
return $items;
|
133 |
|
|
}
|
134 |
|
|
|
135 |
|
|
/**
|
136 |
|
|
* Implements hook_drush_help().
|
137 |
|
|
*/
|
138 |
|
|
function feeds_drush_help($section) {
|
139 |
|
|
switch ($section) {
|
140 |
|
|
case 'drush:feeds-list-importers':
|
141 |
|
|
return dt('Show a list of available Feeds importers with information about them.');
|
142 |
|
|
case 'drush:feeds-list-feeds':
|
143 |
|
|
return dt("List all feed sources. You can limit the number of feed sources to display by setting the option '--limit'.");
|
144 |
|
|
case 'drush:feeds-import':
|
145 |
|
|
$help = dt("Import items from a feed. Follow the command with the importer name to import items with. If the importer is attached to a content type, specify also the feed node with the option '--nid'.");
|
146 |
|
|
$help .= "\n" . dt("Note that the options '--file', '--stdin' and '--url' temporary bypass the configured fetcher and do *not* update the source configuration. For example, if a file was uploaded for the feed source, that file will remain there even when you specify a different file using the '--file' option. Same story applies for when importing from a url. If you omit these options, the last stored source will be used.");
|
147 |
|
|
return $help;
|
148 |
|
|
case 'drush:feeds-import-all':
|
149 |
|
|
return dt('Import items from all feeds. Optionally specify the importer name to import all feeds for.');
|
150 |
|
|
case 'drush:feeds-clear':
|
151 |
|
|
return dt("Delete all items from a feed. Follow the command with the importer name to delete items from. If the importer is attached to a content type, specify also the feed node with the option '--nid'.");
|
152 |
|
|
case 'drush:feeds-enable':
|
153 |
|
|
return dt('Enable the specified Feeds importers. Follow the command with a space delimited list of importer names.');
|
154 |
|
|
case 'drush:feeds-disable':
|
155 |
|
|
return dt('Disable the specified Feeds importers. Follow the command with a space delimited list of importer names.');
|
156 |
|
|
case 'drush:feeds-delete':
|
157 |
|
|
return dt('Delete the specified Feeds importers. Follow the command with a space delimited list of importer names.');
|
158 |
|
|
case 'drush:feeds-revert':
|
159 |
|
|
return dt('Revert the specified Feeds importers. Follow the command with a space delimited list of importer names.');
|
160 |
|
|
}
|
161 |
|
|
}
|
162 |
|
|
|
163 |
|
|
/**
|
164 |
|
|
* Prints a list of all Feeds importers.
|
165 |
|
|
*/
|
166 |
|
|
function drush_feeds_list_importers() {
|
167 |
|
|
if (!$importers = feeds_importer_load_all(TRUE)) {
|
168 |
|
|
drush_print(dt('No importers available.'));
|
169 |
|
|
return;
|
170 |
|
|
}
|
171 |
|
|
|
172 |
|
|
$rows = array();
|
173 |
|
|
|
174 |
|
|
$rows[] = array(
|
175 |
|
|
dt('Name'),
|
176 |
|
|
dt('Description'),
|
177 |
|
|
dt('Attached to'),
|
178 |
|
|
dt('Status'),
|
179 |
|
|
dt('State'),
|
180 |
|
|
);
|
181 |
|
|
|
182 |
|
|
foreach ($importers as $importer) {
|
183 |
|
|
if ($importer->export_type == EXPORT_IN_CODE) {
|
184 |
|
|
$state = dt('Default');
|
185 |
|
|
}
|
186 |
|
|
elseif ($importer->export_type == EXPORT_IN_DATABASE) {
|
187 |
|
|
$state = dt('Normal');
|
188 |
|
|
}
|
189 |
|
|
elseif ($importer->export_type == (EXPORT_IN_CODE | EXPORT_IN_DATABASE)) {
|
190 |
|
|
$state = dt('Overridden');
|
191 |
|
|
}
|
192 |
|
|
|
193 |
|
|
$rows[] = array(
|
194 |
|
|
$importer->config['name'] . ' (' . $importer->id . ')',
|
195 |
|
|
$importer->config['description'],
|
196 |
|
|
$importer->config['content_type'] ? dt(node_type_get_name($importer->config['content_type'])) : dt('none'),
|
197 |
|
|
$importer->disabled ? dt('Disabled') : dt('Enabled'),
|
198 |
|
|
$state,
|
199 |
|
|
);
|
200 |
|
|
}
|
201 |
|
|
|
202 |
|
|
drush_print_table($rows, TRUE);
|
203 |
|
|
}
|
204 |
|
|
|
205 |
|
|
/**
|
206 |
|
|
* Lists all feeds.
|
207 |
|
|
*
|
208 |
|
|
* @param string $importer_id
|
209 |
|
|
* (optional) The importer id.
|
210 |
|
|
*/
|
211 |
|
|
function drush_feeds_list_feeds($importer_id = NULL) {
|
212 |
|
|
if (!$limit = drush_get_option('limit')) {
|
213 |
|
|
$limit = DRUSH_FEEDS_DEFAULT_LIMIT;
|
214 |
|
|
}
|
215 |
|
|
|
216 |
|
|
$header = array(
|
217 |
|
|
'importer_id' => dt('Importer ID'),
|
218 |
|
|
'feed_nid' => dt('Feed NID'),
|
219 |
|
|
'feed_title' => dt('Feed title'),
|
220 |
|
|
'imported' => dt('Last imported'),
|
221 |
|
|
'source' => dt('Feed source'),
|
222 |
|
|
'process_in_background' => dt('Process in background'),
|
223 |
|
|
);
|
224 |
|
|
|
225 |
|
|
$rows = array();
|
226 |
|
|
$nids = array();
|
227 |
|
|
|
228 |
|
|
foreach (_drush_feeds_get_all($importer_id, $limit) as $feed) {
|
229 |
|
|
$feed_config = feeds_source($feed->id, $feed->feed_nid)->importer->getConfig();
|
230 |
|
|
|
231 |
|
|
$rows[] = array(
|
232 |
|
|
'importer_id' => $feed->id,
|
233 |
|
|
'feed_nid' => $feed->feed_nid,
|
234 |
|
|
'feed_title' => '',
|
235 |
|
|
'imported' => $feed->imported ? date('Y-m-d H:i:s', $feed->imported) : dt('Never'),
|
236 |
|
|
'source' => is_scalar($feed->source) ? $feed->source : gettype($feed->source),
|
237 |
|
|
'process_in_background' => !empty($feed_config['process_in_background']) ? dt('Yes') : dt('No'),
|
238 |
|
|
);
|
239 |
|
|
|
240 |
|
|
// Collect node ID's to find titles for.
|
241 |
|
|
if ($feed->feed_nid) {
|
242 |
|
|
$nids[] = $feed->feed_nid;
|
243 |
|
|
}
|
244 |
|
|
}
|
245 |
|
|
|
246 |
|
|
// Find titles for feed nodes.
|
247 |
|
|
if (count($nids)) {
|
248 |
|
|
$nodes = db_select('node')
|
249 |
|
|
->fields('node', array('nid', 'title'))
|
250 |
|
|
->condition('nid', $nids)
|
251 |
|
|
->execute()
|
252 |
|
|
->fetchAllKeyed();
|
253 |
|
|
|
254 |
|
|
foreach ($rows as &$row) {
|
255 |
|
|
$nid = $row['feed_nid'];
|
256 |
|
|
if ($nid && isset($nodes[$nid])) {
|
257 |
|
|
$row['feed_title'] = $nodes[$nid];
|
258 |
|
|
}
|
259 |
|
|
}
|
260 |
|
|
}
|
261 |
|
|
|
262 |
|
|
// Check if there were any results.
|
263 |
|
|
if (count($rows) == 0) {
|
264 |
|
|
if (empty($importer_id)) {
|
265 |
|
|
drush_print(dt('There are no feed sources.'));
|
266 |
|
|
}
|
267 |
|
|
else {
|
268 |
|
|
drush_print(dt("No feed sources exists for importer '@importer_id'.", array(
|
269 |
|
|
'@importer_id' => $importer_id,
|
270 |
|
|
)));
|
271 |
|
|
}
|
272 |
|
|
return FALSE;
|
273 |
|
|
}
|
274 |
|
|
|
275 |
|
|
// Create table.
|
276 |
|
|
$table = array_merge(array($header), $rows);
|
277 |
|
|
|
278 |
|
|
drush_print_table($table, TRUE);
|
279 |
|
|
}
|
280 |
|
|
|
281 |
|
|
/**
|
282 |
|
|
* Imports a given importer/source.
|
283 |
|
|
*
|
284 |
|
|
* @param string $importer_id
|
285 |
|
|
* (optional) The importer id to filter on.
|
286 |
|
|
*/
|
287 |
|
|
function drush_feeds_import($importer_id = NULL) {
|
288 |
|
|
if (!strlen($importer_id)) {
|
289 |
|
|
drush_set_error(dt("Please specify the importer to import items with. If the importer is attached to a content type, specify also the feed node with the option '--nid'."));
|
290 |
|
|
return FALSE;
|
291 |
|
|
}
|
292 |
|
|
|
293 |
|
|
if (!$feed_nid = drush_get_option('nid')) {
|
294 |
|
|
$feed_nid = 0;
|
295 |
|
|
}
|
296 |
|
|
|
297 |
|
|
try {
|
298 |
|
|
$source = feeds_source($importer_id, $feed_nid)->existing();
|
299 |
|
|
}
|
300 |
|
|
catch (FeedsNotExistingException $e) {
|
301 |
|
|
$importer = feeds_importer_load($importer_id);
|
302 |
|
|
if (!$importer) {
|
303 |
|
|
drush_set_error(dt("The importer '@importer' does not exist or is not enabled.", array(
|
304 |
|
|
'@importer' => $importer_id,
|
305 |
|
|
)));
|
306 |
|
|
return FALSE;
|
307 |
|
|
}
|
308 |
|
|
|
309 |
|
|
if ($feed_nid == 0) {
|
310 |
|
|
// Check if the importer is a standalone importer.
|
311 |
|
|
if ($importer->config['content_type']) {
|
312 |
|
|
drush_set_error(dt("The importer '@importer' is attached to a content type. Please specify the feed node to import items for with the option '--nid'. To show a list of available feed nodes for this importer, use 'drush feeds-list-feeds @importer'.", array(
|
313 |
|
|
'@importer' => $importer_id,
|
314 |
|
|
)));
|
315 |
|
|
return FALSE;
|
316 |
|
|
}
|
317 |
|
|
elseif (drush_get_option('file') || drush_get_option('url') || drush_get_option('stdin')) {
|
318 |
|
|
// Create a new source.
|
319 |
|
|
$source = feeds_source($importer_id);
|
320 |
|
|
$source->save();
|
321 |
|
|
}
|
322 |
|
|
}
|
323 |
|
|
elseif (!$importer->config['content_type']) {
|
324 |
|
|
$message = dt("The importer '@importer' is not attached to a content type. Do you want to import items for this importer?", array(
|
325 |
|
|
'@importer' => $importer_id,
|
326 |
|
|
));
|
327 |
|
|
|
328 |
|
|
if (!drush_confirm($message)) {
|
329 |
|
|
return drush_log(dt('Aborting.'), 'ok');
|
330 |
|
|
}
|
331 |
|
|
else {
|
332 |
|
|
drush_set_option('nid', 0);
|
333 |
|
|
// Avoid asking for confirmation twice.
|
334 |
|
|
drush_set_option('feeds_import_skip_confirm', 1);
|
335 |
|
|
return drush_feeds_import($importer_id);
|
336 |
|
|
}
|
337 |
|
|
}
|
338 |
|
|
|
339 |
|
|
if (empty($source)) {
|
340 |
|
|
// Only abort at this point when no source object exists. It can exist
|
341 |
|
|
// when the importer is not attached to a content type and a file, url or
|
342 |
|
|
// stdin is supplied.
|
343 |
|
|
if ($feed_nid == 0) {
|
344 |
|
|
drush_set_error(dt("No source exists yet for the importer '@importer'. There is nothing to import. You can import from a file or url using the options '--file' or '--url' or go to /import/@importer to configure the source to import. See 'drush help feeds-import' for more information.", array(
|
345 |
|
|
'@importer' => $importer_id,
|
346 |
|
|
)));
|
347 |
|
|
return FALSE;
|
348 |
|
|
}
|
349 |
|
|
else {
|
350 |
|
|
drush_set_error(dt("There is no feed node with ID @nid for importer '@importer'. To show a list of available feed nodes for this importer, use 'drush feeds-list-feeds @importer'.", array(
|
351 |
|
|
'@importer' => $importer_id,
|
352 |
|
|
'@nid' => $feed_nid,
|
353 |
|
|
)));
|
354 |
|
|
return FALSE;
|
355 |
|
|
}
|
356 |
|
|
}
|
357 |
|
|
}
|
358 |
|
|
|
359 |
|
|
// Propose confirmation message.
|
360 |
|
|
$messages = array();
|
361 |
|
|
$vars = array(
|
362 |
|
|
'@importer' => $importer_id,
|
363 |
|
|
'@feed_nid' => $feed_nid,
|
364 |
|
|
);
|
365 |
|
|
if ($feed_nid) {
|
366 |
|
|
$messages[] = dt("Items will be imported with the importer '@importer' for the feed node @feed_nid.", $vars);
|
367 |
|
|
}
|
368 |
|
|
else {
|
369 |
|
|
$messages[] = dt("Items will be imported with the importer '@importer'.", $vars);
|
370 |
|
|
}
|
371 |
|
|
|
372 |
|
|
$result = NULL;
|
373 |
|
|
if ($filename = drush_get_option('file')) {
|
374 |
|
|
$filepath = _drush_feeds_find_file($filename);
|
375 |
|
|
if (!is_file($filepath)) {
|
376 |
|
|
drush_set_error(dt("The file '@file' does not exist.", array('@file' => $filename)));
|
377 |
|
|
return FALSE;
|
378 |
|
|
}
|
379 |
|
|
else {
|
380 |
|
|
$filepath = realpath($filepath);
|
381 |
|
|
}
|
382 |
|
|
$result = new FeedsFileFetcherResult($filepath);
|
383 |
|
|
|
384 |
|
|
$messages[] = dt("The items will be imported from the file '@file'.", array(
|
385 |
|
|
'@file' => $filepath,
|
386 |
|
|
));
|
387 |
|
|
}
|
388 |
|
|
elseif ($url = drush_get_option('url')) {
|
389 |
|
|
$result = new FeedsHTTPFetcherResult($url);
|
390 |
|
|
|
391 |
|
|
$messages[] = dt("The items will be imported from the url '@url'.", array(
|
392 |
|
|
'@url' => $url,
|
393 |
|
|
));
|
394 |
|
|
}
|
395 |
|
|
elseif (drush_get_option('stdin')) {
|
396 |
|
|
$result = new FeedsFetcherResult(file_get_contents('php://stdin'));
|
397 |
|
|
|
398 |
|
|
$messages[] = dt('The items will be imported from stdin.');
|
399 |
|
|
}
|
400 |
|
|
|
401 |
|
|
// Only ask for confirmation if it wasn't already asked before. See above.
|
402 |
|
|
if (!drush_get_option('feeds_import_skip_confirm')) {
|
403 |
|
|
$messages[] = dt('Do you really want to continue?');
|
404 |
|
|
$message = implode(' ', $messages);
|
405 |
|
|
if (!drush_confirm($message)) {
|
406 |
|
|
return drush_log(dt('Aborting.'), 'ok');
|
407 |
|
|
}
|
408 |
|
|
}
|
409 |
|
|
|
410 |
|
|
// Start the import!
|
411 |
|
|
if ($result) {
|
412 |
|
|
try {
|
413 |
|
|
$source->pushImport($result);
|
414 |
|
|
}
|
415 |
|
|
catch (Exception $e) {
|
416 |
|
|
drush_set_error($e->getMessage());
|
417 |
|
|
return FALSE;
|
418 |
|
|
}
|
419 |
|
|
}
|
420 |
|
|
else {
|
421 |
|
|
_drush_feeds_create_import_batch($importer_id, $feed_nid);
|
422 |
|
|
drush_backend_batch_process();
|
423 |
|
|
return;
|
424 |
|
|
}
|
425 |
|
|
}
|
426 |
|
|
|
427 |
|
|
/**
|
428 |
|
|
* Imports all feeds.
|
429 |
|
|
*
|
430 |
|
|
* @param string $importer_id
|
431 |
|
|
* (optional) The importer id to filter on.
|
432 |
|
|
*/
|
433 |
|
|
function drush_feeds_import_all($importer_id = NULL) {
|
434 |
|
|
if (!$limit = drush_get_option('limit')) {
|
435 |
|
|
$limit = DRUSH_FEEDS_DEFAULT_LIMIT;
|
436 |
|
|
}
|
437 |
|
|
|
438 |
|
|
// Set flag for whether or not executing the batch. When all importers are not
|
439 |
|
|
// not confirmed there are no batches set and in that case there are no
|
440 |
|
|
// batches to process.
|
441 |
|
|
$execute_batch = FALSE;
|
442 |
|
|
|
443 |
|
|
foreach (_drush_feeds_get_all($importer_id, $limit) as $feed) {
|
444 |
|
|
if (!isset($feed->source) || !strlen($feed->source)) {
|
445 |
|
|
continue;
|
446 |
|
|
}
|
447 |
|
|
|
448 |
|
|
try {
|
449 |
|
|
$source = feeds_source($feed->id, $feed->feed_nid)->existing();
|
450 |
|
|
}
|
451 |
|
|
catch (FeedsNotExistingException $e) {
|
452 |
|
|
continue;
|
453 |
|
|
}
|
454 |
|
|
|
455 |
|
|
// Compose messages.
|
456 |
|
|
$vars = array(
|
457 |
|
|
'@importer_id' => $source->id,
|
458 |
|
|
'@feed_nid' => $source->feed_nid,
|
459 |
|
|
);
|
460 |
|
|
if ($source->feed_nid) {
|
461 |
|
|
$feed_node = node_load($source->feed_nid);
|
462 |
|
|
if ($feed_node) {
|
463 |
|
|
$vars['@title'] = $feed_node->title;
|
464 |
|
|
}
|
465 |
|
|
else {
|
466 |
|
|
drush_set_error(dt('The feed node @feed_nid (@importer_id) does not exist.', $vars));
|
467 |
|
|
continue;
|
468 |
|
|
}
|
469 |
|
|
$confirm_message = dt("Do you want to import items with the importer '@importer_id' for the feed '@title'?", $vars);
|
470 |
|
|
$skip_message = dt("Skipping importer '@importer_id' for feed '@title'.", $vars);
|
471 |
|
|
}
|
472 |
|
|
else {
|
473 |
|
|
$confirm_message = dt("Do you want to import items with the importer '@importer_id'?", $vars);
|
474 |
|
|
$skip_message = dt("Skipping importer '@importer_id'.", $vars);
|
475 |
|
|
}
|
476 |
|
|
|
477 |
|
|
if (drush_confirm($confirm_message)) {
|
478 |
|
|
_drush_feeds_create_import_batch($feed->id, $feed->feed_nid);
|
479 |
|
|
$execute_batch = TRUE;
|
480 |
|
|
}
|
481 |
|
|
else {
|
482 |
|
|
drush_log($skip_message, 'ok');
|
483 |
|
|
}
|
484 |
|
|
}
|
485 |
|
|
|
486 |
|
|
if ($execute_batch) {
|
487 |
|
|
drush_backend_batch_process();
|
488 |
|
|
}
|
489 |
|
|
}
|
490 |
|
|
|
491 |
|
|
/**
|
492 |
|
|
* Creates a batch job for an import.
|
493 |
|
|
*
|
494 |
|
|
* @param string $importer_id
|
495 |
|
|
* The importer id.
|
496 |
|
|
* @param int $feed_nid
|
497 |
|
|
* The feed node id.
|
498 |
|
|
*/
|
499 |
|
|
function _drush_feeds_create_import_batch($importer_id, $feed_nid) {
|
500 |
|
|
$feed_node = FALSE;
|
501 |
|
|
if ($feed_nid) {
|
502 |
|
|
if (!$feed_node = node_load($feed_nid)) {
|
503 |
|
|
drush_set_error(dt('The feed node @feed_nid (@importer_id) does not exist.', array('@importer_id' => $importer_id, '@feed_nid' => $feed_nid)));
|
504 |
|
|
return FALSE;
|
505 |
|
|
}
|
506 |
|
|
}
|
507 |
|
|
|
508 |
|
|
$title = $feed_node ? $feed_node->title . ' (' . $importer_id . ')' : $importer_id;
|
509 |
|
|
|
510 |
|
|
drush_log(dt('Importing: @title', array('@title' => $title)), 'ok');
|
511 |
|
|
|
512 |
|
|
$batch = array(
|
513 |
|
|
'title' => '',
|
514 |
|
|
'operations' => array(
|
515 |
|
|
array('feeds_batch', array('import', $importer_id, $feed_nid)),
|
516 |
|
|
),
|
517 |
|
|
'progress_message' => '',
|
518 |
|
|
);
|
519 |
|
|
|
520 |
|
|
batch_set($batch);
|
521 |
|
|
}
|
522 |
|
|
|
523 |
|
|
/**
|
524 |
|
|
* Clears a Feeds importer.
|
525 |
|
|
*
|
526 |
|
|
* @param string $importer_id
|
527 |
|
|
* The importer id to clean.
|
528 |
|
|
*/
|
529 |
|
|
function drush_feeds_clear($importer_id = NULL) {
|
530 |
|
|
if (!strlen($importer_id)) {
|
531 |
|
|
drush_set_error(dt("Please specify the importer to delete all imported items from. If the importer is attached to a content type, specify also the feed node with the option '--nid'."));
|
532 |
|
|
return FALSE;
|
533 |
|
|
}
|
534 |
|
|
|
535 |
|
|
if (!$feed_nid = drush_get_option('nid')) {
|
536 |
|
|
$feed_nid = 0;
|
537 |
|
|
}
|
538 |
|
|
|
539 |
|
|
try {
|
540 |
|
|
feeds_source($importer_id, $feed_nid)->existing();
|
541 |
|
|
}
|
542 |
|
|
catch (FeedsNotExistingException $e) {
|
543 |
|
|
$importer = feeds_importer_load($importer_id);
|
544 |
|
|
if (!$importer) {
|
545 |
|
|
drush_set_error(dt("The importer '@importer' does not exist or is not enabled.", array(
|
546 |
|
|
'@importer' => $importer_id,
|
547 |
|
|
)));
|
548 |
|
|
return FALSE;
|
549 |
|
|
}
|
550 |
|
|
|
551 |
|
|
if ($feed_nid == 0) {
|
552 |
|
|
// Check if the importer is a standalone importer.
|
553 |
|
|
if ($importer->config['content_type']) {
|
554 |
|
|
drush_set_error(dt("The importer '@importer' is attached to a content type. Please specify the feed node to delete items from with the option '--nid'. To show a list of available feed nodes for this importer, use 'drush feeds-list-feeds @importer'.", array(
|
555 |
|
|
'@importer' => $importer_id,
|
556 |
|
|
)));
|
557 |
|
|
return FALSE;
|
558 |
|
|
}
|
559 |
|
|
}
|
560 |
|
|
elseif (!$importer->config['content_type']) {
|
561 |
|
|
$message = dt("The importer '@importer' is not attached to a content type. Do you want to clear all items for this importer?", array(
|
562 |
|
|
'@importer' => $importer_id,
|
563 |
|
|
));
|
564 |
|
|
|
565 |
|
|
if (!drush_confirm($message)) {
|
566 |
|
|
return drush_log(dt('Aborting.'), 'ok');
|
567 |
|
|
}
|
568 |
|
|
else {
|
569 |
|
|
drush_set_option('nid', 0);
|
570 |
|
|
// Avoid asking for confirmation twice.
|
571 |
|
|
drush_set_option('feeds_clear_skip_confirm', 1);
|
572 |
|
|
return drush_feeds_clear($importer_id);
|
573 |
|
|
}
|
574 |
|
|
}
|
575 |
|
|
|
576 |
|
|
drush_set_error(dt("There is no feed node with ID @nid for importer '@importer'. To show a list of available feed nodes for this importer, use 'drush feeds-list-feeds @importer'.", array(
|
577 |
|
|
'@importer' => $importer_id,
|
578 |
|
|
'@nid' => $feed_nid,
|
579 |
|
|
)));
|
580 |
|
|
return FALSE;
|
581 |
|
|
}
|
582 |
|
|
|
583 |
|
|
// Only ask for confirmation if it wasn't already asked before. See above.
|
584 |
|
|
if (!drush_get_option('feeds_clear_skip_confirm')) {
|
585 |
|
|
if ($feed_nid) {
|
586 |
|
|
$message = dt("All items imported with the importer '@importer' for the feed node @feed_nid will be deleted. Do you really want to continue?", array(
|
587 |
|
|
'@importer' => $importer_id,
|
588 |
|
|
'@feed_nid' => $feed_nid,
|
589 |
|
|
));
|
590 |
|
|
}
|
591 |
|
|
else {
|
592 |
|
|
$message = dt("All items imported with the importer '@importer' will be deleted. Do you really want to continue?", array(
|
593 |
|
|
'@importer' => $importer_id,
|
594 |
|
|
));
|
595 |
|
|
}
|
596 |
|
|
if (!drush_confirm($message)) {
|
597 |
|
|
return drush_log(dt('Aborting.'), 'ok');
|
598 |
|
|
}
|
599 |
|
|
}
|
600 |
|
|
|
601 |
|
|
$batch = array(
|
602 |
|
|
'title' => dt('Clearing !importer', array('!importer' => $importer_id)),
|
603 |
|
|
'operations' => array(
|
604 |
|
|
array('feeds_batch', array('clear', $importer_id, $feed_nid)),
|
605 |
|
|
),
|
606 |
|
|
);
|
607 |
|
|
|
608 |
|
|
batch_set($batch);
|
609 |
|
|
drush_backend_batch_process();
|
610 |
|
|
}
|
611 |
|
|
|
612 |
|
|
/**
|
613 |
|
|
* Enables a set of Feeds importers.
|
614 |
|
|
*/
|
615 |
|
|
function drush_feeds_enable() {
|
616 |
|
|
$all = array_keys(feeds_importer_load_all(TRUE));
|
617 |
|
|
$enabled = array_keys(feeds_importer_load_all());
|
618 |
|
|
$missing = array_diff(func_get_args(), $all);
|
619 |
|
|
$to_enable = array_diff(func_get_args(), $enabled, $missing);
|
620 |
|
|
$already_enabled = array_intersect(func_get_args(), $enabled);
|
621 |
|
|
|
622 |
|
|
if ($missing) {
|
623 |
|
|
drush_print(dt('The following importers are missing: !importers', array('!importers' => implode(', ', $missing))));
|
624 |
|
|
}
|
625 |
|
|
|
626 |
|
|
if ($already_enabled) {
|
627 |
|
|
drush_print(dt('The following importers are already enabled: !importers', array('!importers' => implode(', ', $already_enabled))));
|
628 |
|
|
}
|
629 |
|
|
|
630 |
|
|
if ($to_enable) {
|
631 |
|
|
drush_print(dt('The following importers will be enabled: !importers', array('!importers' => implode(', ', $to_enable))));
|
632 |
|
|
}
|
633 |
|
|
elseif (count(func_get_args()) == 0) {
|
634 |
|
|
return drush_set_error(dt('Please specify a space delimited list of importers to enable.'));
|
635 |
|
|
}
|
636 |
|
|
else {
|
637 |
|
|
return drush_print(dt('There are no importers to enable.'));
|
638 |
|
|
}
|
639 |
|
|
|
640 |
|
|
if (!drush_confirm(dt('Do you really want to continue?'))) {
|
641 |
|
|
return drush_log(dt('Aborting.'), 'ok');
|
642 |
|
|
}
|
643 |
|
|
|
644 |
|
|
$disabled = variable_get('default_feeds_importer', array());
|
645 |
|
|
|
646 |
|
|
foreach ($to_enable as $importer_id) {
|
647 |
|
|
unset($disabled[$importer_id]);
|
648 |
|
|
drush_log(dt("The importer '!importer' has been enabled.", array('!importer' => $importer_id)), 'ok');
|
649 |
|
|
}
|
650 |
|
|
|
651 |
|
|
variable_set('default_feeds_importer', $disabled);
|
652 |
|
|
feeds_cache_clear();
|
653 |
|
|
}
|
654 |
|
|
|
655 |
|
|
/**
|
656 |
|
|
* Disables a set of Feeds importers.
|
657 |
|
|
*/
|
658 |
|
|
function drush_feeds_disable() {
|
659 |
|
|
$all = array_keys(feeds_importer_load_all(TRUE));
|
660 |
|
|
$enabled = array_keys(feeds_importer_load_all());
|
661 |
|
|
$to_disable = array_intersect(func_get_args(), $enabled);
|
662 |
|
|
$missing = array_diff(func_get_args(), $all);
|
663 |
|
|
$already_disabled = array_diff(func_get_args(), $enabled, $missing);
|
664 |
|
|
|
665 |
|
|
if ($missing) {
|
666 |
|
|
drush_print(dt('The following importers are missing: !importers', array('!importers' => implode(', ', $missing))));
|
667 |
|
|
}
|
668 |
|
|
|
669 |
|
|
if ($already_disabled) {
|
670 |
|
|
drush_print(dt('The following importers are already disabled: !importers', array('!importers' => implode(', ', $already_disabled))));
|
671 |
|
|
}
|
672 |
|
|
|
673 |
|
|
if ($to_disable) {
|
674 |
|
|
drush_print(dt('The following importers will be disabled: !importers', array('!importers' => implode(', ', $to_disable))));
|
675 |
|
|
}
|
676 |
|
|
elseif (count(func_get_args()) == 0) {
|
677 |
|
|
return drush_set_error(dt('Please specify a space delimited list of importers to disable.'));
|
678 |
|
|
}
|
679 |
|
|
else {
|
680 |
|
|
return drush_print(dt('There are no importers to disable.'));
|
681 |
|
|
}
|
682 |
|
|
|
683 |
|
|
if (!drush_confirm(dt('Do you really want to continue?'))) {
|
684 |
|
|
return drush_log(dt('Aborting.'), 'ok');
|
685 |
|
|
}
|
686 |
|
|
|
687 |
|
|
$disabled = variable_get('default_feeds_importer', array());
|
688 |
|
|
foreach ($to_disable as $importer_id) {
|
689 |
|
|
$disabled[$importer_id] = TRUE;
|
690 |
|
|
drush_log(dt("The importer '!importer' has been disabled.", array('!importer' => $importer_id)), 'ok');
|
691 |
|
|
}
|
692 |
|
|
|
693 |
|
|
variable_set('default_feeds_importer', $disabled);
|
694 |
|
|
feeds_cache_clear();
|
695 |
|
|
}
|
696 |
|
|
|
697 |
|
|
/**
|
698 |
|
|
* Deletes a set of Feeds importers.
|
699 |
|
|
*/
|
700 |
|
|
function drush_feeds_delete() {
|
701 |
|
|
$all = feeds_importer_load_all(TRUE);
|
702 |
|
|
$to_delete = array_intersect_key($all, array_flip(func_get_args()));
|
703 |
|
|
$missing = array_diff(func_get_args(), array_keys($all));
|
704 |
|
|
$cant_delete = array();
|
705 |
|
|
|
706 |
|
|
// Filter out default importers that are not overridden.
|
707 |
|
|
foreach ($to_delete as $delta => $importer) {
|
708 |
|
|
if ($importer->export_type === EXPORT_IN_CODE) {
|
709 |
|
|
unset($to_delete[$delta]);
|
710 |
|
|
$cant_delete[$importer->id] = $importer->id;
|
711 |
|
|
}
|
712 |
|
|
}
|
713 |
|
|
|
714 |
|
|
if ($missing) {
|
715 |
|
|
drush_print(dt('The following importers are missing: !importers', array('!importers' => implode(', ', $missing))));
|
716 |
|
|
}
|
717 |
|
|
|
718 |
|
|
if ($cant_delete) {
|
719 |
|
|
drush_print(dt('The following importers cannot be deleted because they only exist in code: !importers', array('!importers' => implode(', ', array_keys($cant_delete)))));
|
720 |
|
|
}
|
721 |
|
|
|
722 |
|
|
if ($to_delete) {
|
723 |
|
|
drush_print(dt('The following importers will be deleted: !importers', array('!importers' => implode(', ', array_keys($to_delete)))));
|
724 |
|
|
}
|
725 |
|
|
elseif (count(func_get_args()) == 0) {
|
726 |
|
|
return drush_set_error(dt('Please specify a space delimited list of importers to delete.'));
|
727 |
|
|
}
|
728 |
|
|
else {
|
729 |
|
|
return drush_print(dt('There are no importers to delete.'));
|
730 |
|
|
}
|
731 |
|
|
|
732 |
|
|
if (!drush_confirm(dt('Do you really want to continue?'))) {
|
733 |
|
|
return drush_log(dt('Aborting.'), 'ok');
|
734 |
|
|
}
|
735 |
|
|
|
736 |
|
|
foreach ($to_delete as $importer) {
|
737 |
|
|
$importer->delete();
|
738 |
|
|
drush_log(dt("The importer '!importer' was deleted successfully.", array('!importer' => $importer->id)), 'ok');
|
739 |
|
|
}
|
740 |
|
|
|
741 |
|
|
feeds_cache_clear();
|
742 |
|
|
}
|
743 |
|
|
|
744 |
|
|
/**
|
745 |
|
|
* Reverts a set of feeds.
|
746 |
|
|
*/
|
747 |
|
|
function drush_feeds_revert() {
|
748 |
|
|
$all = feeds_importer_load_all(TRUE);
|
749 |
|
|
$missing = array_diff(func_get_args(), array_keys($all));
|
750 |
|
|
$to_revert = array_intersect_key($all, array_flip(func_get_args()));
|
751 |
|
|
$cant_revert = array();
|
752 |
|
|
$cant_revert_db = array();
|
753 |
|
|
|
754 |
|
|
// Filter out non-overridden importers.
|
755 |
|
|
foreach ($to_revert as $delta => $importer) {
|
756 |
|
|
if ($importer->export_type !== (EXPORT_IN_CODE | EXPORT_IN_DATABASE)) {
|
757 |
|
|
unset($to_revert[$delta]);
|
758 |
|
|
if ($importer->export_type == EXPORT_IN_DATABASE) {
|
759 |
|
|
$cant_revert_db[$importer->id] = $importer->id;
|
760 |
|
|
}
|
761 |
|
|
else {
|
762 |
|
|
$cant_revert[$importer->id] = $importer->id;
|
763 |
|
|
}
|
764 |
|
|
}
|
765 |
|
|
}
|
766 |
|
|
|
767 |
|
|
if ($missing) {
|
768 |
|
|
drush_print(dt('The following importers are missing: !importers', array('!importers' => implode(', ', $missing))));
|
769 |
|
|
}
|
770 |
|
|
|
771 |
|
|
if ($cant_revert) {
|
772 |
|
|
drush_print(dt('The following importers cannot be reverted because they are not overridden: !importers', array('!importers' => implode(', ', array_keys($cant_revert)))));
|
773 |
|
|
}
|
774 |
|
|
if ($cant_revert_db) {
|
775 |
|
|
drush_print(dt('The following importers cannot be reverted because they only exist in the database: !importers', array('!importers' => implode(', ', array_keys($cant_revert_db)))));
|
776 |
|
|
}
|
777 |
|
|
|
778 |
|
|
if ($to_revert) {
|
779 |
|
|
drush_print(dt('The following importers will be reverted: !importers', array('!importers' => implode(', ', array_keys($to_revert)))));
|
780 |
|
|
}
|
781 |
|
|
elseif (count(func_get_args()) == 0) {
|
782 |
|
|
return drush_set_error(dt('Please specify a space delimited list of importers to revert.'));
|
783 |
|
|
}
|
784 |
|
|
else {
|
785 |
|
|
return drush_print(dt('There are no importers to revert.'));
|
786 |
|
|
}
|
787 |
|
|
|
788 |
|
|
if (!drush_confirm(dt('Do you really want to continue?'))) {
|
789 |
|
|
return drush_log(dt('Aborting.'), 'ok');
|
790 |
|
|
}
|
791 |
|
|
|
792 |
|
|
foreach ($to_revert as $importer) {
|
793 |
|
|
$importer->delete();
|
794 |
|
|
drush_log(dt("The importer '!importer' was reverted successfully.", array('!importer' => $importer->id)), 'ok');
|
795 |
|
|
}
|
796 |
|
|
|
797 |
|
|
feeds_cache_clear();
|
798 |
|
|
}
|
799 |
|
|
|
800 |
|
|
/**
|
801 |
|
|
* Returns all feed instances filtered by an optional importer.
|
802 |
|
|
*
|
803 |
|
|
* @param string $importer_id
|
804 |
|
|
* (optional) The importer id.
|
805 |
|
|
* @param int $limit
|
806 |
|
|
* (optional) The number of feeds to return.
|
807 |
|
|
*
|
808 |
|
|
* @return DatabaseStatementInterface
|
809 |
|
|
* A list of feeds objects.
|
810 |
|
|
*/
|
811 |
|
|
function _drush_feeds_get_all($importer_id = NULL, $limit = DRUSH_FEEDS_DEFAULT_LIMIT) {
|
812 |
|
|
if (isset($importer_id)) {
|
813 |
|
|
return db_query_range("SELECT * FROM {feeds_source} WHERE id = :importer ORDER BY imported ASC", 0, $limit, array(':importer' => $importer_id));
|
814 |
|
|
}
|
815 |
|
|
|
816 |
|
|
return db_query_range("SELECT * FROM {feeds_source} ORDER BY imported ASC", 0, $limit);
|
817 |
|
|
}
|
818 |
|
|
|
819 |
|
|
/**
|
820 |
|
|
* Tries to find the specified file at several locations.
|
821 |
|
|
*
|
822 |
|
|
* @param string $filename
|
823 |
|
|
* The file to look for.
|
824 |
|
|
*
|
825 |
|
|
* @return string
|
826 |
|
|
* If found, the file that was found.
|
827 |
|
|
* NULL otherwise.
|
828 |
|
|
*/
|
829 |
|
|
function _drush_feeds_find_file($filename) {
|
830 |
|
|
// If the full path to the file is specified, the file will be found right away.
|
831 |
|
|
if (is_file($filename)) {
|
832 |
|
|
// Found!
|
833 |
|
|
return $filename;
|
834 |
|
|
}
|
835 |
|
|
|
836 |
|
|
// Look for the file within the current active directory.
|
837 |
|
|
$search = drush_cwd() . '/' . $filename;
|
838 |
|
|
if (is_file($search)) {
|
839 |
|
|
// Found!
|
840 |
|
|
return $search;
|
841 |
|
|
}
|
842 |
|
|
|
843 |
|
|
// Look for the file within the directory Drupal is installed in.
|
844 |
|
|
// bootstrap_drupal_root() sets the active directory to the Drupal root.
|
845 |
|
|
$search = getcwd() . '/' . $filename;
|
846 |
|
|
if (is_file($search)) {
|
847 |
|
|
// Found!
|
848 |
|
|
return $search;
|
849 |
|
|
}
|
850 |
|
|
} |