Skip to content

Commit

Permalink
Move cache handling code to own file.
Browse files Browse the repository at this point in the history
  • Loading branch information
netcarver committed Nov 26, 2017
1 parent f083eb0 commit a291585
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 112 deletions.
78 changes: 78 additions & 0 deletions FileCache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php namespace Netcarver;

class FileCache {
/**
*
*/
protected $cache_dir = null;


/**
*
*/
public function setCacheDirectory($dir = null) {
if (is_string($dir) && !empty($dir)) {
$this->cache_dir = realpath("$dir/");
} else {
$this->cache_dir = dirname(__FILE__) . "/cache";
}
}



/**
*
*/
protected function urlToKey($url) {
$key = str_replace('https://', '', strtolower($url));
$key = str_replace(['/',':','?','#', '%'], '-', $key);
return $key;
}




/**
*
*/
protected function keyToStorageLocation($key) {
$dir = $this->cache_dir;
if (!$dir || !is_readable($dir)) {
throw new \Exception("Cache directory is invalid or unreadable.");
}
$location = "{$this->cache_dir}/$key";
return $location;
}



/**
*
*/
protected function getEntryForKey($key) {
$file = $this->keyToStorageLocation($key);
$entry = @file_get_contents($file);
if ($entry) {
if (is_callable('gzinflate')) {
$entry = gzinflate($entry);
}
$entry = json_decode($entry, true);
return $entry;
}
return null;
}



/**
*
*/
protected function setEntryForKey($key, $entry) {
$file = $this->keyToStorageLocation($key);
$entry = json_encode($entry);
if (is_callable('gzdeflate')) {
$entry = gzdeflate($entry);
}
file_put_contents($file, $entry);
}
}
2 changes: 2 additions & 0 deletions GitRepositoryInterface.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<?php namespace Netcarver;

interface GitRepositoryInterface {
public function __construct($http, $remote, $application, array $options);
public function GetInfo();
public function GetTags();
public function GetCommits($startref, $endref='HEAD');
public function GetChangelog();
public function GetForks($sort);
}
144 changes: 39 additions & 105 deletions GithubInterface.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php namespace Netcarver;

require_once 'FileCache.php';
require_once 'GitRepositoryInterface.php';


Expand All @@ -15,15 +16,14 @@
* - Consider adding OAUTH token support.
*
*/
class GithubInterface implements GitRepositoryInterface {
class GithubInterface extends FileCache implements GitRepositoryInterface {

// Per-instance data...
protected $remote = null;
protected $owner = null;
protected $repo = null;
protected $http = null;
protected $tags = null;
protected $cache = null;
protected $headers = [];

// Data common across all instances...
Expand All @@ -39,11 +39,16 @@ class GithubInterface implements GitRepositoryInterface {
'tag-to-tag-commits',
'changelog-access',
'commits',
'forks'
'forks',
],
];


/**
* Returns information about this repository interface.
*
* This is a mixture of static and per-instance information.
*/
public function GetInfo() {
return array_merge(
self::$info,
Expand All @@ -57,21 +62,17 @@ public function GetInfo() {
}


protected function setReadInfo($headers) {
if (isset($headers['x-ratelimit-remaining'])) {
self::$info['remaining'] = $headers['x-ratelimit-remaining'];
self::$info['limit'] = $headers['x-ratelimit-limit'];
self::$info['reset'] = $headers['x-ratelimit-reset'];
}

}


public function __construct($http, $remote, $application, $cache_dir) {
public function __construct($http, $remote, $application, array $options) {
$owner = '';
$repo = '';
$m = [];
$this->setCacheDirectory($cache_dir);

if (array_key_exists('cache_dir', $options)) {
$this->setCacheDirectory($options['cache_dir']);
} else {
throw new \Exception('Cache directory is needed.');
}
$ok = preg_match('~^https?://github.com/([^/]++)/(.++)~i', $remote, $m);
if ($ok) {
$this->headers['Accept'] = 'application/vnd.github.v3+json'; // As requested by the github v3 api documentation.
Expand All @@ -89,6 +90,9 @@ public function __construct($http, $remote, $application, $cache_dir) {
}


/**
* Returns the URL for humans to review the Release Notes at GH.
*/
public function GetReleaseNoteViewUrl($version) {
$encoded_version = rawurlencode($version);
return "https://github.com/$this->encoded_owner}/{$this->encoded_repo}/releases/tags/$encoded_version";
Expand Down Expand Up @@ -119,7 +123,7 @@ public function GetReleaseNotes($version=null) {
$encoded_version = '/tags/' . rawurlencode($version);
}
$url = "https://api.github.com/repos/{$this->encoded_owner}/{$this->encoded_repo}/releases$encoded_version";
$reply = $this->cachedRead($url);
$reply = $this->RepositoryRead($url);
if(200 == $this->http->getHttpCode() && !empty($reply['body'])) {
return $reply['body'];
}
Expand All @@ -131,7 +135,7 @@ public function GetReleaseNotes($version=null) {
public function GetTags() {
if (null === $this->tags) {
$url = "https://api.github.com/repos/{$this->encoded_owner}/{$this->encoded_repo}/git/refs/tags";
$reply = $this->cachedRead($url);
$reply = $this->RepositoryRead($url);
$code = $this->http->getHttpCode();
if(200 == $code || 304 == $code) {
$result = [];
Expand Down Expand Up @@ -189,7 +193,7 @@ public function GetCommits($startref, $endref='HEAD') {
if ($slice > 30) $slice = 30;
}

$reply = $this->cachedRead($url);
$reply = $this->RepositoryRead($url);
$http_code = $this->http->getHttpCode();
if(200 == $http_code || 304 == $http_code) {
if ($slice) {
Expand Down Expand Up @@ -220,7 +224,7 @@ public function GetCommits($startref, $endref='HEAD') {

public function GetChangelog() {
$url = "https://raw.githubusercontent.com/{$this->encoded_owner}/{$this->encoded_repo}/master/CHANGELOG.md";
return $this->cachedRead($url, false);
return $this->RepositoryRead($url, false);
}


Expand All @@ -230,97 +234,15 @@ public function GetForks($sort) {
$sort = 'newest';
}
$url = "https://api.github.com/repos/{$this->encoded_owner}/{$this->encoded_repo}/forks?sort=$sort&page=1";
return $this->cachedRead($url);
}



/**
*
*/
protected $cache_dir = null;


/**
*
*/
public function setCacheDirectory($dir = null) {
if (is_string($dir) && !empty($dir)) {
$this->cache_dir = realpath("$dir/");
} else {
$this->cache_dir = dirname(__FILE__) . "/cache";
}
}



/**
*
*/
protected function urlToKey($url) {
$key = str_replace('https://', '', strtolower($url));
$key = str_replace(['/',':','?','#', '%'], '-', $key);
return $key;
}




/**
*
*/
protected function keyToStorageLocation($key) {
$dir = $this->cache_dir;
if (!$dir || !is_readable($dir)) {
throw new \Exception("Cache directory is invalid or unreadable.");
}
$location = "{$this->cache_dir}/$key";
return $location;
}



/**
*
*/
protected function getEntryForKey($key) {
$file = $this->keyToStorageLocation($key);
$entry = @file_get_contents($file);
if ($entry) {
if (is_callable('gzinflate')) {
$entry = gzinflate($entry);
}
$entry = json_decode($entry, true);
return $entry;
} else {
return [
'reply' => null,
'etag' => null,
'last_mod' => null,
];
}
return $this->RepositoryRead($url);
}



/**
*
*/
protected function setEntryForKey($key, $entry) {
$file = $this->keyToStorageLocation($key);
$entry = json_encode($entry);
if (is_callable('gzdeflate')) {
$entry = gzdeflate($entry);
}
file_put_contents($file, $entry);
}



/**
*
*/
protected function cachedRead($url, $json = true) {
protected function RepositoryRead($url, $json = true) {
$reply = null;
$etag = null;
$last_mod = null;
Expand All @@ -343,16 +265,22 @@ protected function cachedRead($url, $json = true) {
$new_reply = ($json) ? $this->http->getJson($url) : $this->http->get($url);
$http_code = $this->http->getHttpCode();
$response_headers = $this->http->getResponseHeaders();
$this->setReadInfo($response_headers);
if (isset($response_headers['x-ratelimit-remaining'])) {
self::$info['remaining'] = $response_headers['x-ratelimit-remaining'];
self::$info['limit'] = $response_headers['x-ratelimit-limit'];
self::$info['reset'] = $response_headers['x-ratelimit-reset'];
}

switch ($http_code) {
case 200:
/**
* Cache miss, but we now have the values from the headers and body that we can store in the cache.
*/
$entry['etag'] = @$response_headers['etag'];
$entry['last_mod'] = @$response_headers['Last-Modified'];
$entry['reply'] = $new_reply;
$this->setEntryForKey($key, $entry);
$reply = $new_reply;

break;

case 301:
Expand All @@ -370,8 +298,14 @@ protected function cachedRead($url, $json = true) {
$new_url = $response_headers['Location'];
break;


case 304:
/**
* Cache hit! File contents are already in the cache!
*/
break;

case 403:
case 404:
break;
}

Expand Down
8 changes: 1 addition & 7 deletions ModuleReleaseNotes.module
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,7 @@ class ModuleReleaseNotes extends Process implements ConfigurableModule {
if (!is_dir($cache_dir) && !mkdir($cache_dir)) {
throw new \Exception(sprintf(__("Could not create cache directory at %s, is the assets directory writable?"), $cache_dir));
}
$client = new \Netcarver\GithubInterface($http, $remote, $application, $cache_dir);
/* $client->setCacheDirectory($cache_dir); */
$client = new \Netcarver\GithubInterface($http, $remote, $application, ['cache_dir' => $cache_dir]);
} else if (false !== stripos($remote, '://bitbucket.org')) {
// TODO develop bitbucket client
} else if (false !== stripos($remote, '://gitlab.com')) {
Expand Down Expand Up @@ -204,10 +203,7 @@ class ModuleReleaseNotes extends Process implements ConfigurableModule {
$current_version = $current_info['version'];
$new_version = $info['module_version']; // This is a string.
$remote = $info['project_url'];
//$remote_info = $this->remoteHostInfo($remote);
//$repo_icon = $remote_info['icon'];
$remote_icon = '<i class="fa fa-icon fa-external-link"></i>';
//$is_github = 'Github' == $remote_info['host'];

$info['version_current'] = $current_version; // Push the current version into the $info
if (is_int($current_version)) {
Expand All @@ -220,9 +216,7 @@ class ModuleReleaseNotes extends Process implements ConfigurableModule {

$changes = $current_version != $new_version;
$version_order = version_compare($current_version, $new_version);
//\TD::barDump("Current v[$current_version], new v[$new_version], version_order[$version_order]");
if ($version_order == 0) {
//\TD::barDump("Exiting as there are no changes!");
return; // No change!
}

Expand Down

0 comments on commit a291585

Please sign in to comment.