Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
F
feeds
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Model registry
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
drupal.org
feeds
Commits
f36dbcb9
Commit
f36dbcb9
authored
7 years ago
by
megachriz
Committed by
Megachriz
7 years ago
Browse files
Options
Downloads
Patches
Plain Diff
Issue #2868134 by MegaChriz: Show next time that the source will be imported.
parent
3f06cb6d
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
feeds.pages.inc
+27
-0
27 additions, 0 deletions
feeds.pages.inc
includes/FeedsSource.inc
+125
-0
125 additions, 0 deletions
includes/FeedsSource.inc
tests/feeds_scheduler.test
+101
-0
101 additions, 0 deletions
tests/feeds_scheduler.test
with
253 additions
and
0 deletions
feeds.pages.inc
+
27
−
0
View file @
f36dbcb9
...
...
@@ -301,6 +301,7 @@ function feeds_source_status($source) {
}
$v
[
'imported'
]
=
$source
->
imported
;
$v
[
'count'
]
=
$source
->
itemCount
();
$v
[
'next'
]
=
$source
->
getNextImportTimeDetails
();
if
(
!
empty
(
$v
))
{
return
theme
(
'feeds_source_status'
,
$v
);
}
...
...
@@ -331,6 +332,32 @@ function theme_feeds_source_status($v) {
$items
[]
=
t
(
'No imported items.'
);
}
}
if
(
$v
[
'next'
])
{
// Check if medium date format contains hours/minutes.
$date_format
=
variable_get
(
'date_format_medium'
);
$use_custom_date_format
=
$date_format
&&
!
strpos
(
$date_format
,
'H:i'
);
if
(
!
empty
(
$v
[
'next'
][
'message'
]))
{
$items
[]
=
t
(
'Next import: @message.'
,
array
(
'@message'
=>
$v
[
'next'
][
'message'
],
));
}
elseif
(
$v
[
'next'
][
'time'
]
>
REQUEST_TIME
)
{
$items
[]
=
t
(
'Next import: @date (via @method)'
,
array
(
'@date'
=>
$use_custom_date_format
?
format_date
(
$v
[
'next'
][
'time'
],
'custom'
,
'Y/m/d H:i:s'
)
:
format_date
(
$v
[
'next'
][
'time'
]),
'@method'
=>
$v
[
'next'
][
'method'
],
));
}
else
{
$items
[]
=
t
(
'Next import: on next cron run (via @method).'
,
array
(
'@method'
=>
$v
[
'next'
][
'method'
],
));
}
}
else
{
$items
[]
=
t
(
'Next import: not scheduled.'
);
}
$output
.
=
theme
(
'item_list'
,
array
(
'items'
=>
$items
));
$output
.
=
'</div>'
;
return
$output
;
...
...
This diff is collapsed.
Click to expand it.
includes/FeedsSource.inc
+
125
−
0
View file @
f36dbcb9
...
...
@@ -665,6 +665,131 @@ class FeedsSource extends FeedsConfigurable {
return
$this
->
importer
->
processor
->
itemCount
(
$this
);
}
/**
* Returns the next time that the feed will be imported.
*
* @return int|null
* The next time the feed will be imported as a UNIX timestamp.
* NULL if not known.
*/
public
function
getNextImportTime
()
{
$details
=
$this
->
getNextImportTimeDetails
();
if
(
isset
(
$details
[
'time'
]))
{
return
$details
[
'time'
];
}
}
/**
* Returns the next time that the feed will be imported.
*
* @return array|null
* Information about when the next time the feed will be imported:
* - time: the next time the feed will be imported as a UNIX timestamp.
* - method: via which scheduler the job will ran.
* - message: If set, time and method should be ignored.
* Null if no information is available.
*/
public
function
getNextImportTimeDetails
()
{
// Check queue.
$serialized_job_type
=
db_like
(
strtr
(
's:4:"type";s:!length:"!type";'
,
array
(
'!length'
=>
strlen
(
$this
->
id
),
'!type'
=>
$this
->
id
,
)));
$serialized_job_id_as_string
=
db_like
(
strtr
(
's:2:"id";s:!length:"!id";'
,
array
(
'!length'
=>
strlen
(
$this
->
feed_nid
),
'!id'
=>
$this
->
feed_nid
,
)));
$serialized_job_id_as_integer
=
db_like
(
strtr
(
's:2:"id";i:!id;'
,
array
(
'!id'
=>
$this
->
feed_nid
,
)));
$queue_created
=
db_select
(
'queue'
)
->
fields
(
'queue'
,
array
(
'created'
))
->
condition
(
'name'
,
'feeds_source_import'
)
->
condition
(
'data'
,
'%'
.
$serialized_job_type
.
'%'
,
'LIKE'
)
->
condition
(
db_or
()
->
condition
(
'data'
,
'%'
.
$serialized_job_id_as_string
.
'%'
,
'LIKE'
)
->
condition
(
'data'
,
'%'
.
$serialized_job_id_as_integer
.
'%'
,
'LIKE'
)
)
->
condition
(
'expire'
,
0
)
->
execute
()
->
fetchField
();
if
(
$queue_created
)
{
return
array
(
'time'
=>
$queue_created
,
'method'
=>
t
(
'Queue'
),
);
}
// Special case for PostgreSQL: if using that database type, we cannot
// search in the data column of the queue table, because the Drupal database
// layer adds '::text' to bytea columns, which results into the data column
// becoming unreadable in conditions. So instead, we check for the first 10
// records in the queue to see if the given importer ID + feed NID is
// amongst them.
if
(
Database
::
getConnection
()
->
databaseType
()
==
'pgsql'
)
{
$items
=
db_query
(
"SELECT data, created FROM
{
queue
}
WHERE name = :name AND expire = 0 LIMIT 10"
,
array
(
':name'
=>
'feeds_source_import'
,
));
foreach
(
$items
as
$item
)
{
if
(
is_string
(
$item
->
data
))
{
$item
->
data
=
unserialize
(
$item
->
data
);
}
if
(
$item
->
data
[
'type'
]
==
$this
->
id
&&
$item
->
data
[
'id'
]
==
$this
->
feed_nid
)
{
return
array
(
'time'
=>
$item
->
created
,
'method'
=>
t
(
'Queue'
),
);
}
}
// If not found by now, count how many items there are in the
// feeds_source_import queue. We use this number later to indicate that
// the job *could* be in the queue.
$number_of_queue_items
=
db_query
(
'SELECT COUNT(name) FROM {queue} WHERE name = :name AND expire = 0'
,
array
(
':name'
=>
'feeds_source_import'
,
))
->
fetchField
();
}
// Check if the importer is in the process of being rescheduled.
$importers
=
feeds_reschedule
();
if
(
isset
(
$importers
[
$this
->
id
]))
{
return
array
(
'time'
=>
NULL
,
'method'
=>
NULL
,
'message'
=>
t
(
'to be rescheduled'
),
);
}
// Check job scheduler.
$job
=
db_select
(
'job_schedule'
)
->
fields
(
'job_schedule'
,
array
(
'next'
,
'scheduled'
))
->
condition
(
'name'
,
'feeds_source_import'
)
->
condition
(
'type'
,
$this
->
id
)
->
condition
(
'id'
,
$this
->
feed_nid
)
->
execute
()
->
fetch
();
if
(
isset
(
$job
->
next
))
{
$details
=
array
(
'time'
=>
$job
->
next
,
'method'
=>
t
(
'Job scheduler'
),
);
if
(
!
empty
(
$job
->
scheduled
))
{
if
(
isset
(
$number_of_queue_items
)
&&
$number_of_queue_items
>
10
)
{
// When using PostgreSQL we were not able to efficiently search the
// queue table, so it could still be in that table.
$details
[
'message'
]
=
t
(
'unknown, could still be in the queue'
);
}
else
{
$details
[
'message'
]
=
t
(
'possibly stuck'
);
}
}
return
$details
;
}
}
/**
* Unlocks a feed.
*/
...
...
This diff is collapsed.
Click to expand it.
tests/feeds_scheduler.test
+
101
−
0
View file @
f36dbcb9
...
...
@@ -210,6 +210,107 @@ class FeedsSchedulerTestCase extends FeedsWebTestCase {
)));
}
/**
* Tests if the expected next import time is shown for scheduled imports.
*/
public
function
testNextImportTime
()
{
$this
->
initSyndication
();
$this
->
drupalLogin
(
$this
->
admin_user
);
// Set schedule to be 25 minutes in the future.
$next
=
REQUEST_TIME
+
1500
;
db_query
(
"UPDATE
{
job_schedule
}
SET next = :time"
,
array
(
':time'
=>
$next
,
));
$this
->
drupalGet
(
'node/1/import'
);
$this
->
assertText
(
format_date
(
$next
));
// Set schedule to import on next cron run.
db_query
(
"UPDATE
{
job_schedule
}
SET next = :time"
,
array
(
':time'
=>
REQUEST_TIME
,
));
$this
->
drupalGet
(
'node/1/import'
);
$this
->
assertText
(
'Next import: on next cron run'
);
// Now remove all jobs.
db_truncate
(
'job_schedule'
)
->
execute
();
// Assert that the import is not scheduled now.
$this
->
drupalGet
(
'node/1/import'
);
$this
->
assertText
(
'Next import: not scheduled'
);
}
/**
* Tests if the expected next import time is shown when the import is queued
* via background job.
*/
public
function
testNextImportTimeWhenQueuedViaBackgroundJob
()
{
// Create an importer that uses a background job to import.
$this
->
createImporterConfiguration
(
'Node import'
,
'node'
);
$edit
=
array
(
'content_type'
=>
''
,
'import_on_create'
=>
TRUE
,
'process_in_background'
=>
TRUE
,
);
$this
->
drupalPost
(
'admin/structure/feeds/node/settings'
,
$edit
,
'Save'
);
$this
->
setPlugin
(
'node'
,
'FeedsFileFetcher'
);
$this
->
setPlugin
(
'node'
,
'FeedsCSVParser'
);
$mappings
=
array
(
0
=>
array
(
'source'
=>
'title'
,
'target'
=>
'title'
,
),
);
$this
->
addMappings
(
'node'
,
$mappings
);
// Specify a file with many nodes.
$this
->
importFile
(
'node'
,
$this
->
absolutePath
()
.
'/tests/feeds/many_nodes.csv'
);
// Verify that a queue item is created.
$count
=
db_query
(
"SELECT COUNT(*) FROM
{
queue
}
WHERE name = 'feeds_source_import'"
)
->
fetchField
();
$this
->
assertEqual
(
1
,
$count
,
format_string
(
'One import item is queued (actual: @count).'
,
array
(
'@count'
=>
$count
,
)));
// The page should say that import happens on next cron.
$this
->
assertText
(
'Next import: on next cron run'
);
}
/**
* Tests if the expected next import time is shown when the import is queued
* via Job Scheduler.
*/
public
function
testNextImportTimeWhenQueuedViaJobScheduler
()
{
$this
->
initSyndication
();
$this
->
drupalLogin
(
$this
->
admin_user
);
// Manually dispatch a job.
$job
=
db_select
(
'job_schedule'
,
NULL
,
array
(
'fetch'
=>
PDO
::
FETCH_ASSOC
))
->
fields
(
'job_schedule'
)
->
condition
(
'type'
,
'syndication'
)
->
condition
(
'id'
,
18
)
->
execute
()
->
fetch
();
try
{
JobScheduler
::
get
(
$job
[
'name'
])
->
dispatch
(
$job
);
$this
->
pass
(
'No exceptions occurred while dispatching a feeds job.'
);
}
catch
(
Exception
$e
)
{
watchdog_exception
(
'feeds'
,
$e
);
$this
->
fail
(
'No exceptions occurred while dispatching a feeds job.'
);
}
// Verify that a queue item is created.
$count
=
db_query
(
"SELECT COUNT(*) FROM
{
queue
}
WHERE name = 'feeds_source_import'"
)
->
fetchField
();
$this
->
assertEqual
(
1
,
$count
,
format_string
(
'One import item is queued (actual: @count).'
,
array
(
'@count'
=>
$count
,
)));
// The page should say that import happens on next cron.
$this
->
drupalGet
(
'node/18/import'
);
$this
->
assertText
(
'Next import: on next cron run'
);
}
/**
* Test batching on cron.
*/
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment