refactor all functions into classes + methods
This commit is contained in:
parent
94c6027fa3
commit
5d5f3d07eb
288
freifunkmeta.php
288
freifunkmeta.php
|
@ -1,9 +1,9 @@
|
|||
<?php
|
||||
/*
|
||||
/**
|
||||
Plugin Name: Freifunk Metadata Shortcodes
|
||||
Plugin URI: http://mschuette.name/
|
||||
Description: Defines shortcodes to display Freifunk metadata
|
||||
Version: 0.2
|
||||
Version: 0.3
|
||||
Author: Martin Schuette
|
||||
Author URI: http://mschuette.name/
|
||||
*/
|
||||
|
@ -12,88 +12,141 @@ define('FF_META_DEFAULT_CACHETIME', 15);
|
|||
define('FF_META_DEFAULT_DIR', 'https://raw.githubusercontent.com/freifunk/directory.api.freifunk.net/master/directory.json');
|
||||
define('FF_META_DEFAULT_CITY', 'hamburg');
|
||||
|
||||
/**
|
||||
* class to fetch and cache data from external URLs
|
||||
*/
|
||||
class FF_Meta_Externaldata
|
||||
{
|
||||
public function get($url) {
|
||||
/* gets metadata from URL, handles caching */
|
||||
function ff_meta_getmetadata ($url) {
|
||||
$url_hash = hash('crc32', $url);
|
||||
$cachekey = 'ff_metadata_'.hash('crc32', $url);
|
||||
$cachetime = get_option('ff_meta_cachetime', FF_META_DEFAULT_CACHETIME) * MINUTE_IN_SECONDS;
|
||||
|
||||
// Caching
|
||||
if ( false === ( $metajson = get_transient( "ff_metadata_${url_hash}" ) ) ) {
|
||||
$metajson = wp_remote_retrieve_body( wp_remote_get($url) );
|
||||
$cachetime = get_option( 'ff_meta_cachetime', FF_META_DEFAULT_CACHETIME) * MINUTE_IN_SECONDS;
|
||||
set_transient( "ff_metadata_${url_hash}", $metajson, $cachetime );
|
||||
if ( false === ( $data = get_transient($cachekey) ) ) {
|
||||
$json = wp_remote_retrieve_body(wp_remote_get($url));
|
||||
$data = json_decode ($json, $assoc = true);
|
||||
set_transient( $cachekey, $data, $cachetime );
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
$metadata = json_decode ( $metajson, $assoc = true );
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
if ( ! shortcode_exists( 'ff_state' ) ) {
|
||||
add_shortcode( 'ff_state', 'ff_meta_shortcode_handler');
|
||||
/**
|
||||
* holds the community directory
|
||||
*/
|
||||
class FF_Directory
|
||||
{
|
||||
private $directory;
|
||||
|
||||
function __construct() {
|
||||
$this->directory = FF_Meta_Externaldata::get(FF_META_DEFAULT_DIR);
|
||||
}
|
||||
if ( ! shortcode_exists( 'ff_services' ) ) {
|
||||
add_shortcode( 'ff_services', 'ff_meta_shortcode_handler');
|
||||
}
|
||||
if ( ! shortcode_exists( 'ff_contact' ) ) {
|
||||
add_shortcode( 'ff_contact', 'ff_meta_shortcode_handler');
|
||||
}
|
||||
if ( ! shortcode_exists( 'ff_location' ) ) {
|
||||
add_shortcode( 'ff_location', 'ff_meta_shortcode_handler');
|
||||
}
|
||||
// Example:
|
||||
// [ff_state]
|
||||
// [ff_state hamburg]
|
||||
function ff_meta_shortcode_handler( $atts, $content, $name ) {
|
||||
// $atts[0] holds the city name, if given
|
||||
if (empty($atts[0])) {
|
||||
$city = get_option( 'ff_meta_city', FF_META_DEFAULT_CITY );
|
||||
|
||||
function get_url_by_city($city) {
|
||||
$val = $this->directory[$city];
|
||||
|
||||
if (empty($val)) {
|
||||
return false;
|
||||
} else {
|
||||
$city = $atts[0];
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (false === ($directory = ff_meta_getmetadata ( FF_META_DEFAULT_DIR ))
|
||||
|| empty($directory[$city])) {
|
||||
/**
|
||||
* OO interface to handle a single community/city
|
||||
*/
|
||||
class FF_Community
|
||||
{
|
||||
public $name;
|
||||
public $street;
|
||||
public $zip;
|
||||
public $city;
|
||||
public $lon;
|
||||
public $lat;
|
||||
|
||||
/**
|
||||
* Default constructor from metadata
|
||||
*/
|
||||
function __construct($metadata) {
|
||||
$loc = $metadata['location'];
|
||||
$this->name = (isset($loc['address']) && isset($loc['address']['Name'])) ? $loc['address']['Name'] : '';
|
||||
$this->street = (isset($loc['address']) && isset($loc['address']['Street'])) ? $loc['address']['Street'] : '';
|
||||
$this->zip = (isset($loc['address']) && isset($loc['address']['Zipcode'])) ? $loc['address']['Zipcode'] : '';
|
||||
$this->city = isset($loc['city']) ? $loc['city'] : '';
|
||||
$this->lon = isset($loc['lon']) ? $loc['lon'] : '';
|
||||
$this->lat = isset($loc['lat']) ? $loc['lat'] : '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative constructor from city name
|
||||
*/
|
||||
static function make_from_city($city) {
|
||||
// TODO: test
|
||||
if (false === ($url = $this->dir->get_url_by_city($city))) {
|
||||
return "<!-- FF Meta Error: cannot get directory.json, or no URL for '$city' -->\n";
|
||||
}
|
||||
$url = $directory[$city];
|
||||
|
||||
if (false === ($metadata = ff_meta_getmetadata ($url))) {
|
||||
if (false === ($metadata = FF_Meta_Externaldata::get($url))) {
|
||||
return "<!-- FF Meta Error: cannot get metadata from $url -->\n";
|
||||
}
|
||||
|
||||
$outstr = "<div class=\"ff $name\">";
|
||||
switch ($name) {
|
||||
case 'ff_state':
|
||||
$state = $metadata['state'];
|
||||
$outstr .= sprintf('%s', $state['nodes']);
|
||||
break;
|
||||
|
||||
case 'ff_location':
|
||||
// normal per-city code
|
||||
$loc = $metadata['location'];
|
||||
$loc_name = (isset($loc['address']) && isset($loc['address']['Name'])) ? $loc['address']['Name'] : '';
|
||||
$loc_street = (isset($loc['address']) && isset($loc['address']['Street'])) ? $loc['address']['Street'] : '';
|
||||
$loc_zip = (isset($loc['address']) && isset($loc['address']['Zipcode'])) ? $loc['address']['Zipcode'] : '';
|
||||
$loc_city = isset($loc['city']) ? $loc['city'] : '';
|
||||
$loc_lon = isset($loc['lon']) ? $loc['lon'] : '';
|
||||
$loc_lat = isset($loc['lat']) ? $loc['lat'] : '';
|
||||
if (empty($loc_name) || empty($loc_street) || empty($loc_zip)) {
|
||||
return '';
|
||||
return new FF_Community($metadata);
|
||||
}
|
||||
|
||||
function format_address() {
|
||||
if (empty($this->name) || empty($this->street) || empty($this->zip)) {
|
||||
return '';
|
||||
}
|
||||
// TODO: style address + map as single box
|
||||
// TODO: once it is "ready" package openlayers.js into the plugin (cf. http://docs.openlayers.org/library/deploying.html)
|
||||
// TODO: handle missing values (i.e. only name & city)
|
||||
$outstr .= '<p>';
|
||||
$outstr .= sprintf('%s<br/>%s<br/>%s %s',
|
||||
$loc_name, $loc_street, $loc_zip, $loc_city);
|
||||
$outstr .= '</p>';
|
||||
return '<p>' . sprintf('%s<br/>%s<br/>%s %s', $this->name, $this->street, $this->zip, $this->city) . '</p>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* main class for whole plugin
|
||||
*/
|
||||
class FF_Meta
|
||||
{
|
||||
private $dir;
|
||||
|
||||
function __construct() {
|
||||
$this->dir = new FF_Directory();
|
||||
}
|
||||
|
||||
function register_stuff() {
|
||||
if ( ! shortcode_exists('ff_state') ) {
|
||||
add_shortcode('ff_state', array($this, 'shortcode_handler'));
|
||||
}
|
||||
if ( ! shortcode_exists('ff_services') ) {
|
||||
add_shortcode('ff_services', array($this, 'shortcode_handler'));
|
||||
}
|
||||
if ( ! shortcode_exists('ff_contact') ) {
|
||||
add_shortcode('ff_contact', array($this, 'shortcode_handler'));
|
||||
}
|
||||
if ( ! shortcode_exists('ff_location') ) {
|
||||
add_shortcode('ff_location', array($this, 'shortcode_handler'));
|
||||
}
|
||||
|
||||
add_action('admin_menu', array($this, 'admin_menu'));
|
||||
add_action('admin_init', array($this, 'admin_init'));
|
||||
register_uninstall_hook( __FILE__, array('ff_meta', 'uninstall_hook'));
|
||||
}
|
||||
|
||||
function output_ff_state($citydata) {
|
||||
$state = $citydata['state'];
|
||||
return sprintf('%s', $state['nodes']);
|
||||
}
|
||||
|
||||
function aux_get_all_locations() {
|
||||
// gather all location data
|
||||
if ( false === ( $json_locs = get_transient( "ff_metadata_json_locs" ) ) ) {
|
||||
if (false === ( $json_locs = get_transient("FF_metadata_json_locs") )) {
|
||||
$all_locs = array();
|
||||
$arr_select = array('lat' => 1, 'lon' => 1);
|
||||
foreach ($directory as $tmp_city => $url) {
|
||||
foreach ($this->dir as $tmp_city => $url) {
|
||||
try {
|
||||
$tmp_meta = ff_meta_getmetadata($url);
|
||||
$tmp_meta = FF_Meta_Externaldata::get($url);
|
||||
if (!empty($tmp_meta['location'])) {
|
||||
$tmp_loc = array_intersect_key($tmp_meta['location'], $arr_select);
|
||||
$all_locs[$tmp_city] = $tmp_loc;
|
||||
|
@ -103,9 +156,18 @@ function ff_meta_shortcode_handler( $atts, $content, $name ) {
|
|||
}
|
||||
}
|
||||
$json_locs = json_encode($all_locs);
|
||||
$cachetime = get_option( 'ff_meta_cachetime', FF_META_DEFAULT_CACHETIME) * MINUTE_IN_SECONDS;
|
||||
set_transient( "ff_metadata_json_locs", $json_locs, $cachetime );
|
||||
$cachetime = get_option('FF_meta_cachetime', FF_META_DEFAULT_CACHETIME) * MINUTE_IN_SECONDS;
|
||||
set_transient("FF_metadata_json_locs", $json_locs, $cachetime);
|
||||
}
|
||||
return $json_locs;
|
||||
}
|
||||
|
||||
function output_ff_location($citydata) {
|
||||
// normal per-city code
|
||||
$loc = new FF_Community($citydata);
|
||||
|
||||
$outstr = $loc->format_address();
|
||||
$json_locs = $this->aux_get_all_locations();
|
||||
|
||||
if (!empty($loc_name) && !empty($loc_name)) {
|
||||
$icon_url = plugin_dir_url(__FILE__) . "freifunk_marker.png";
|
||||
|
@ -119,10 +181,10 @@ function ff_meta_shortcode_handler( $atts, $content, $name ) {
|
|||
|
||||
<script src="http://www.openlayers.org/api/OpenLayers.js"></script>
|
||||
<script>
|
||||
map = new OpenLayers.Map("mapdiv_$loc_city");
|
||||
map = new OpenLayers.Map("mapdiv_$loc->city");
|
||||
map.addLayer(new OpenLayers.Layer.OSM());
|
||||
|
||||
var lonLat = new OpenLayers.LonLat( $loc_lon, $loc_lat )
|
||||
var lonLat = new OpenLayers.LonLat( $loc->lon, $loc->lat )
|
||||
.transform(
|
||||
new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984
|
||||
map.getProjectionObject() // to Spherical Mercator Projection
|
||||
|
@ -152,24 +214,24 @@ function ff_meta_shortcode_handler( $atts, $content, $name ) {
|
|||
</script>
|
||||
EOT;
|
||||
}
|
||||
break;
|
||||
return $outstr;
|
||||
}
|
||||
|
||||
case 'ff_services':
|
||||
$outstr .= '<ul>';
|
||||
if (isset($metadata['services'])) {
|
||||
$services = $metadata['services'];
|
||||
function output_ff_services($citydata) {
|
||||
$outstr = '<ul>';
|
||||
if (isset($citydata['services'])) {
|
||||
$services = $citydata['services'];
|
||||
foreach ($services as $service) {
|
||||
$outstr .= sprintf('<li>%s (%s): <a href="%s">%s</a></li>',
|
||||
$service['serviceName'], $service['serviceDescription'],
|
||||
$service['internalUri'], $service['internalUri']);
|
||||
$outstr .= sprintf('<li>%s (%s): <a href="%s">%s</a></li>', $service['serviceName'], $service['serviceDescription'], $service['internalUri'], $service['internalUri']);
|
||||
}
|
||||
}
|
||||
$outstr .= '</ul>';
|
||||
break;
|
||||
return $outstr;
|
||||
}
|
||||
|
||||
case 'ff_contact':
|
||||
$outstr .= '<p>';
|
||||
$contact = $metadata['contact'];
|
||||
function output_ff_contact($citydata) {
|
||||
$outstr = '<p>';
|
||||
$contact = $citydata['contact'];
|
||||
// Output -- rather ugly but the data is not uniform, some fields are URIs, some are usernames, ...
|
||||
if (!empty($contact['email'])) {
|
||||
$outstr .= sprintf("E-Mail: <a href=\"mailto:%s\">%s</a><br />\n", $contact['email'], $contact['email']);
|
||||
|
@ -201,33 +263,59 @@ EOT;
|
|||
$outstr .= sprintf("XMPP: <a href=\"xmpp:%s\">%s</a><br />\n", $contact['jabber'], $contact['jabber']);
|
||||
}
|
||||
$outstr .= '</p>';
|
||||
break;
|
||||
|
||||
default:
|
||||
return "";
|
||||
break;
|
||||
return $outstr;
|
||||
}
|
||||
|
||||
// Output
|
||||
function shortcode_handler($atts, $content, $shortcode) {
|
||||
// $atts[0] holds the city name, if given
|
||||
if (empty($atts[0])) {
|
||||
$city = get_option('FF_meta_city', FF_META_DEFAULT_CITY);
|
||||
} else {
|
||||
$city = $atts[0];
|
||||
}
|
||||
|
||||
if (false === ($cityurl = $this->dir->get_url_by_city($city))) {
|
||||
return "<!-- FF Meta Error: cannot get directory.json, or no URL for '$city' -->\n";
|
||||
}
|
||||
|
||||
if (false === ($metadata = FF_Meta_Externaldata::get($cityurl))) {
|
||||
return "<!-- FF Meta Error: cannot get metadata from $cityurl -->\n";
|
||||
}
|
||||
|
||||
$outstr = "<div class=\"ff $shortcode\">";
|
||||
switch ($shortcode) {
|
||||
case 'ff_state':
|
||||
$outstr .= $this->output_ff_state($metadata);
|
||||
break;
|
||||
case 'ff_location':
|
||||
$outstr .= $this->output_ff_location($metadata);
|
||||
break;
|
||||
case 'ff_services':
|
||||
$outstr .= $this->output_ff_services($metadata);
|
||||
break;
|
||||
case 'ff_contact':
|
||||
$outstr .= $this->output_ff_contact($metadata);
|
||||
break;
|
||||
default:
|
||||
$outstr .= "";
|
||||
break;
|
||||
}
|
||||
$outstr .= "</div>";
|
||||
return $outstr;
|
||||
}
|
||||
|
||||
|
||||
function admin_menu() {
|
||||
// Options Page:
|
||||
add_action( 'admin_menu', 'ff_meta_admin_menu' );
|
||||
function ff_meta_admin_menu() {
|
||||
add_options_page(
|
||||
'FF Meta Plugin', // page title
|
||||
'FF Meta', // menu title
|
||||
'manage_options', // req'd capability
|
||||
'ff_meta_plugin', // menu slug
|
||||
'ff_meta_options_page' // callback function
|
||||
array ('FF_meta', 'options_page') // callback function
|
||||
);
|
||||
}
|
||||
|
||||
add_action( 'admin_init', 'ff_meta_admin_init' );
|
||||
function ff_meta_admin_init() {
|
||||
function admin_init() {
|
||||
register_setting(
|
||||
'ff_meta_settings-group', // group name
|
||||
'ff_meta_cachetime' // option name
|
||||
|
@ -239,13 +327,13 @@ function ff_meta_admin_init() {
|
|||
add_settings_section(
|
||||
'ff_meta_section-one', // ID
|
||||
'Section One', // Title
|
||||
'ff_meta_section_one_callback', // callback to fill
|
||||
array ('FF_Meta', 'section_one_callback'), // callback to fill
|
||||
'ff_meta_plugin' // page to display on
|
||||
);
|
||||
add_settings_field(
|
||||
'ff_meta_city', // ID
|
||||
'Default community', // Title
|
||||
'ff_meta_city_callback', // callback to fill field
|
||||
array ('FF_Meta', 'city_callback'), // callback to fill field
|
||||
'ff_meta_plugin', // menu page=slug to display field on
|
||||
'ff_meta_section-one', // section to display the field in
|
||||
array('label_for' => 'ff_meta_city_id') // ID of input element
|
||||
|
@ -253,25 +341,25 @@ function ff_meta_admin_init() {
|
|||
add_settings_field(
|
||||
'ff_meta_cachetime', // ID
|
||||
'Cache time', // Title
|
||||
'ff_meta_cachetime_callback', // callback to fill field
|
||||
array ('FF_Meta', 'cachetime_callback'), // callback to fill field
|
||||
'ff_meta_plugin', // menu page=slug to display field on
|
||||
'ff_meta_section-one', // section to display the field in
|
||||
array('label_for' => 'ff_meta_cachetime_id') // ID of input element
|
||||
);
|
||||
}
|
||||
|
||||
function ff_meta_section_one_callback() {
|
||||
function section_one_callback() {
|
||||
echo 'This Plugin provides shortcodes to display information from the Freifunk meta.json.';
|
||||
}
|
||||
|
||||
function ff_meta_cachetime_callback() {
|
||||
function cachetime_callback() {
|
||||
$time = get_option( 'ff_meta_cachetime', FF_META_DEFAULT_CACHETIME );
|
||||
echo "<input type='number' name='ff_meta_cachetime' id='ff_meta_cachetime_id' class='small-text code' value='$time' /> minutes"
|
||||
."<p class='description'>Data from external URLs is cached for this number of minutes.</p>";
|
||||
}
|
||||
|
||||
function ff_meta_city_callback() {
|
||||
if (false === ($directory = ff_meta_getmetadata ( FF_META_DEFAULT_DIR ))) {
|
||||
function city_callback() {
|
||||
if (false === ($directory = FF_Meta_Externaldata::get ( FF_META_DEFAULT_DIR ))) {
|
||||
// TODO: error handling
|
||||
return;
|
||||
}
|
||||
|
@ -287,7 +375,7 @@ function ff_meta_city_callback() {
|
|||
echo "<p class='description'>This is the default city parameter.</p>";
|
||||
}
|
||||
|
||||
function ff_meta_options_page() {
|
||||
function options_page() {
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h2>Freifunk Meta Plugin Options</h2>
|
||||
|
@ -300,8 +388,12 @@ function ff_meta_options_page() {
|
|||
<?php
|
||||
}
|
||||
|
||||
register_uninstall_hook( __FILE__, 'ff_meta_uninstall_hook' );
|
||||
function ff_meta_uninstall_hook() {
|
||||
function uninstall_hook() {
|
||||
delete_option( 'ff_meta_city' );
|
||||
delete_option( 'ff_meta_cachetime' );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$ffmeta = new FF_Meta;
|
||||
$ffmeta->register_stuff();
|
||||
|
|
Loading…
Reference in a new issue