Skip to content

Instantly share code, notes, and snippets.

@amygdala
Created December 16, 2013 01:31
Show Gist options
  • Save amygdala/7981101 to your computer and use it in GitHub Desktop.
Save amygdala/7981101 to your computer and use it in GitHub Desktop.
<?php
require_once 'Model.php';
/**
* Model class for feed objects
*/
class FeedModel extends Model {
const FEED_MODEL_KIND = 'FeedModel';
const SUBSCRIBER_URL_NAME = 'subscriber_url';
const ETAG_PROPERTY_NAME = 'etag';
const LAST_CRAWL_DATE_NAME = 'last_crawled';
const SUBSCRIBER_LIST_NAME = 'subscribers';
private $subscriber_url;
private $subscriber_list;
private $etag;
private $last_crawl_date;
public function __construct($url) {
parent::__construct();
$this->key_name = sha1($url);
$this->subscriber_url = $url;
$this->subscriber_list = [];
}
public function getSubscriberUrl() {
return $this->subscriber_url;
}
public function setETag($etag) {
$this->etag = $etag;
}
public function getETag() {
return $this->etag;
}
public function getLastCrawlDate() {
return $this->last_crawl_date;
}
public function setLastCrawlDate($date_time) {
$this->last_crawl_date = $date_time;
}
public function getSubscriberList() {
return $this->subscriber_list;
}
public function addSubscriber($id) {
if ($this->subscriber_list == null) {
$this->subscriber_list = [$id];
return true;
}
if (!in_array($id, $this->subscriber_list)) {
$this->subscriber_list[] = $id;
return true;
}
return false;
}
public function removeSubscriber($id) {
$key = array_search($id, $this->subscriber_list);
if ($key!==false) {
unset($this->subscriber_list[$key]);
return true;
}
return false;
}
protected static function getKindName() {
return self::FEED_MODEL_KIND;
}
/**
* Generate the entity property map from the feed object fields.
*/
protected function getKindProperties() {
$property_map = [];
$property_map[self::SUBSCRIBER_URL_NAME] =
parent::createStringProperty($this->subscriber_url, true);
if ($this->etag) {
$property_map[self::ETAG_PROPERTY_NAME] =
parent::createStringProperty($this->etag);
}
if ($this->last_crawl_date) {
$property_map[self::LAST_CRAWL_DATE_NAME] =
parent::createStringProperty($this->last_crawl_date);
}
if (!empty($this->subscriber_list)) {
$property_map[self::SUBSCRIBER_LIST_NAME] =
parent::createStringListProperty($this->subscriber_list);
}
return $property_map;
}
/**
* Fetch a feed object given its feed URL. If get a cache miss, fetch from the Datastore.
* @param $feed_url URL of the feed.
*/
public static function get($feed_url) {
$mc = new Memcache();
$key = self::getCacheKey($feed_url);
$response = $mc->get($key);
if ($response) {
return [$response];
}
$query = parent::createQuery(self::FEED_MODEL_KIND);
$feed_url_filter = parent::createStringFilter(self::SUBSCRIBER_URL_NAME,
$feed_url);
$filter = parent::createCompositeFilter([$feed_url_filter]);
$query->setFilter($filter);
$results = parent::executeQuery($query);
$extracted = self::extractQueryResults($results);
return $extracted;
}
/**
* This method will be called after a Datastore put.
*/
protected function onItemWrite() {
$mc = new Memcache();
try {
$key = self::getCacheKey($this->subscriber_url);
$mc->add($key, $this, 0, 120);
}
catch (Google_Cache_Exception $ex) {
syslog(LOG_WARNING, "in onItemWrite: memcache exception");
}
}
/**
* This method will be called prior to a datastore delete
*/
protected function beforeItemDelete() {
$mc = new Memcache();
$key = self::getCacheKey($this->subscriber_url);
$mc->delete($key);
}
/**
* Extract the results of a Datastore query into FeedModel objects
* @param $results Datastore query results
*/
protected static function extractQueryResults($results) {
$query_results = [];
foreach($results as $result) {
$id = @$result['entity']['key']['path'][0]['id'];
$key_name = @$result['entity']['key']['path'][0]['name'];
$props = $result['entity']['properties'];
$url = $props[self::SUBSCRIBER_URL_NAME]->getStringValue();
if (isset($props[self::ETAG_PROPERTY_NAME])) {
$etag = @$props[self::ETAG_PROPERTY_NAME]->getStringValue();
}
else {
$etag = null;
}
if (isset($props[self::LAST_CRAWL_DATE_NAME])) {
$last_crawl_date = @$props[self::LAST_CRAWL_DATE_NAME]->getStringValue();
}
else {
$last_crawl_date = null;
}
$subscribers = [];
if (isset($props[self::SUBSCRIBER_LIST_NAME])) {
if (!empty($props[self::SUBSCRIBER_LIST_NAME]['listValue'])) {
$subslist = $props[self::SUBSCRIBER_LIST_NAME]->getListValue();
foreach ($subslist as $s) {
$subscribers[] = $s->getStringValue();
}
}
}
$feed_model = new FeedModel($url);
$feed_model->setKeyId($id);
$feed_model->setKeyName($key_name);
$feed_model->last_crawl_date = $last_crawl_date;
$feed_model->subscriber_list = $subscribers;
$feed_model->etag = $etag;
// Cache this read feed.
$feed_model->onItemWrite();
$query_results[] = $feed_model;
}
return $query_results;
}
private static function getCacheKey($feed_url) {
return sprintf("%s_%s", self::FEED_MODEL_KIND, sha1($feed_url));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment