2017-11-19 17:36:20 +00:00
< ? php
/**
* @ file src / Worker / PubSubPublish . php
*/
namespace Friendica\Worker ;
use Friendica\App ;
use Friendica\Core\System ;
use Friendica\Core\Config ;
use Friendica\Core\Worker ;
use Friendica\Database\DBM ;
use Friendica\Protocol\OStatus ;
2018-01-27 04:24:23 +00:00
use Friendica\Util\Network ;
2018-05-17 22:17:03 +00:00
use Friendica\Util\DateTimeFormat ;
2018-04-09 21:34:23 +00:00
use dba ;
2017-11-19 17:36:20 +00:00
require_once 'include/items.php' ;
class PubSubPublish {
public static function execute ( $pubsubpublish_id = 0 )
{
global $a ;
2018-05-17 22:17:03 +00:00
if ( $pubsubpublish_id != 0 ) {
self :: publish ( $pubsubpublish_id );
return ;
2017-11-19 17:36:20 +00:00
}
2018-05-17 22:17:03 +00:00
// We'll push to each subscriber that has push > 0,
// i.e. there has been an update (set in notifier.php).
$subscribers = dba :: select ( 'push_subscriber' , [ 'id' , 'callback_url' ], [ " `push` > 0 AND `next_try` < UTC_TIMESTAMP() " ]);
while ( $subscriber = dba :: fetch ( $subscribers )) {
logger ( " Publish feed to " . $subscriber [ " callback_url " ], LOGGER_DEBUG );
Worker :: add ([ 'priority' => $a -> queue [ 'priority' ], 'created' => $a -> queue [ 'created' ], 'dont_fork' => true ],
'PubSubPublish' , ( int ) $subscriber [ " id " ]);
}
2017-11-19 17:36:20 +00:00
2018-05-17 22:17:03 +00:00
dba :: close ( $subscribers );
2017-11-19 17:36:20 +00:00
}
private static function publish ( $id ) {
global $a ;
2018-05-17 22:17:03 +00:00
$subscriber = dba :: selectFirst ( 'push_subscriber' , [], [ 'id' => $id ]);
if ( ! DBM :: is_result ( $subscriber )) {
2017-11-19 17:36:20 +00:00
return ;
}
/// @todo Check server status with PortableContact::checkServer()
// Before this can be done we need a way to safely detect the server url.
2018-05-17 22:17:03 +00:00
logger ( " Generate feed of user " . $subscriber [ 'nickname' ] . " to " . $subscriber [ 'callback_url' ] . " - last updated " . $subscriber [ 'last_update' ], LOGGER_DEBUG );
2017-11-19 17:36:20 +00:00
2018-05-17 22:17:03 +00:00
$last_update = $subscriber [ 'last_update' ];
$params = OStatus :: feed ( $subscriber [ 'nickname' ], $last_update );
2017-11-19 17:36:20 +00:00
if ( ! $params ) {
return ;
}
2018-05-17 22:17:03 +00:00
$hmac_sig = hash_hmac ( " sha1 " , $params , $subscriber [ 'secret' ]);
2017-11-19 17:36:20 +00:00
2018-01-15 13:05:12 +00:00
$headers = [ " Content-type: application/atom+xml " ,
2017-11-19 17:36:20 +00:00
sprintf ( " Link: <%s>;rel=hub,<%s>;rel=self " ,
2018-05-17 22:17:03 +00:00
System :: baseUrl () . '/pubsubhubbub/' . $subscriber [ 'nickname' ],
$subscriber [ 'topic' ]),
" X-Hub-Signature: sha1= " . $hmac_sig ];
2017-11-19 17:36:20 +00:00
2018-05-17 22:17:03 +00:00
logger ( 'POST ' . print_r ( $headers , true ) . " \n " . $params , LOGGER_DATA );
2017-11-19 17:36:20 +00:00
2018-05-17 22:17:03 +00:00
Network :: post ( $subscriber [ 'callback_url' ], $params , $headers );
2017-11-19 17:36:20 +00:00
$ret = $a -> get_curl_code ();
2018-05-17 22:17:03 +00:00
$condition = [ 'id' => $subscriber [ 'id' ]];
2017-11-19 17:36:20 +00:00
if ( $ret >= 200 && $ret <= 299 ) {
2018-05-17 22:17:03 +00:00
logger ( 'Successfully pushed to ' . $subscriber [ 'callback_url' ]);
2017-11-19 17:36:20 +00:00
// set last_update to the "created" date of the last item, and reset push=0
2018-05-17 22:17:03 +00:00
$fields = [ 'push' => 0 , 'next_try' => NULL_DATE , 'last_update' => $last_update ];
dba :: update ( 'push_subscriber' , $fields , $condition );
2017-11-19 17:36:20 +00:00
} else {
2018-05-17 22:17:03 +00:00
logger ( 'Delivery error when pushing to ' . $subscriber [ 'callback_url' ] . ' HTTP: ' . $ret );
2017-11-19 17:36:20 +00:00
// we use the push variable also as a counter, if we failed we
// increment this until some upper limit where we give up
2018-05-17 22:17:03 +00:00
$retrial = $subscriber [ 'push' ];
2017-11-19 17:36:20 +00:00
2018-05-17 22:17:03 +00:00
if ( $retrial > 14 ) {
dba :: update ( 'push_subscriber' , [ 'push' => 0 , 'next_try' => NULL_DATE ], $condition );
logger ( 'Delivery error: Giving up for ' . $subscriber [ 'callback_url' ], LOGGER_DEBUG );
} else {
// Calculate the delay until the next trial
$delay = (( $retrial + 3 ) ** 4 ) + ( rand ( 1 , 30 ) * ( $retrial + 1 ));
$next = DateTimeFormat :: utc ( 'now + ' . $delay . ' seconds' );
2017-11-19 17:36:20 +00:00
2018-05-17 22:17:03 +00:00
$retrial = $retrial + 1 ;
dba :: update ( 'push_subscriber' , [ 'push' => $retrial , 'next_try' => $next ], $condition );
logger ( 'Delivery error: Next try (' . $retrial . ') for ' . $subscriber [ 'callback_url' ] . ' at ' . $next , LOGGER_DEBUG );
}
2017-11-19 17:36:20 +00:00
}
}
}