diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 4a880a9..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-bin
-vendor
-composer.lock
-*.sublime-project
-*.sublime-workspace
-nbproject/
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 38b233c..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-language: php
-sudo: false
-
-php:
- - 5.3
- - 5.4
- - 5.5
- - 5.6
- - hhvm
-
-env:
- - WP_VERSION=3.8
- - WP_VERSION=latest
-
-before_script:
- - bash bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION
- - fgrep wp_version /tmp/wordpress/wp-includes/version.php
-
-script: phpunit
diff --git a/README.md b/README.md
index 1b7a199..d8dbcab 100644
--- a/README.md
+++ b/README.md
@@ -1,23 +1,15 @@
# Freifunk Metadata Wordpress Plugin
-[](https://travis-ci.org/mschuett/freifunkmeta)
-
A small Wordpress plugin to render Freifunk metadata according to the [api.freifunk.net](https://github.com/freifunk/api.freifunk.net) specification ([german description](http://freifunk.net/blog/2013/12/die-freifunk-api/)).
It reads (and caches) JSON input from a configured URL and provides shortcodes to output the data.
-Currently implemented are `[ff_services]`, `[ff_contact]`, and `[ff_state]`.
-
-An `[ff_location]` is also usable, but needs more work.
+Currently implemented are `[ff_services]` and `[ff_contact]`.
## Example
Text:
- Location:
-
- [ff_location]
-
Services:
[ff_services]
@@ -28,11 +20,8 @@ Text:
Contact Jena:
- [ff_contact jena]
+ [ff_contact url="http://freifunk-jena.de/jena.json"]
Output:
-
-

-
diff --git a/behat.yml b/behat.yml
deleted file mode 100644
index 6b10c9c..0000000
--- a/behat.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-default:
- context:
- parameters:
- base_url: http://localhost:8080/
- role_map:
- ender: subscriber
- starter: editor
- extensions:
- Behat\MinkExtension\Extension:
- base_url: http://localhost:8080/
- goutte: ~
- selenium2:
- wd_host: http://localhost:8910/wd/hub
- browser_name: phantomjs
- default_session: selenium2
- javascript_session: selenium2
\ No newline at end of file
diff --git a/bin/install-wp-tests.sh b/bin/install-wp-tests.sh
deleted file mode 100644
index 0aaf09f..0000000
--- a/bin/install-wp-tests.sh
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env bash
-
-if [ $# -lt 3 ]; then
- echo "usage: $0 [db-host] [wp-version]"
- exit 1
-fi
-
-DB_NAME=$1
-DB_USER=$2
-DB_PASS=$3
-DB_HOST=${4-localhost}
-WP_VERSION=${5-latest}
-
-WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib}
-WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/}
-
-download() {
- if [ `which curl` ]; then
- curl -s "$1" > "$2";
- elif [ `which wget` ]; then
- wget -nv -O "$2" "$1"
- fi
-}
-
-if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then
- WP_TESTS_TAG="tags/$WP_VERSION"
-else
- # http serves a single offer, whereas https serves multiple. we only want one
- download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json
- grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json
- LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//')
- if [[ -z "$LATEST_VERSION" ]]; then
- echo "Latest WordPress version could not be found"
- exit 1
- fi
- WP_TESTS_TAG="tags/$LATEST_VERSION"
-fi
-
-set -ex
-
-install_wp() {
-
- if [ -d $WP_CORE_DIR ]; then
- return;
- fi
-
- mkdir -p $WP_CORE_DIR
-
- if [ $WP_VERSION == 'latest' ]; then
- local ARCHIVE_NAME='latest'
- else
- local ARCHIVE_NAME="wordpress-$WP_VERSION"
- fi
-
- download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz
- tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR
-
- download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php
-}
-
-install_test_suite() {
- # portable in-place argument for both GNU sed and Mac OSX sed
- if [[ $(uname -s) == 'Darwin' ]]; then
- local ioption='-i .bak'
- else
- local ioption='-i'
- fi
-
- # set up testing suite if it doesn't yet exist
- if [ ! -d $WP_TESTS_DIR ]; then
- # set up testing suite
- mkdir -p $WP_TESTS_DIR
- svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes
- fi
-
- cd $WP_TESTS_DIR
-
- if [ ! -f wp-tests-config.php ]; then
- download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php
- sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php
- sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php
- sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php
- sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php
- sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php
- fi
-
-}
-
-install_db() {
- # parse DB_HOST for port or socket references
- local PARTS=(${DB_HOST//\:/ })
- local DB_HOSTNAME=${PARTS[0]};
- local DB_SOCK_OR_PORT=${PARTS[1]};
- local EXTRA=""
-
- if ! [ -z $DB_HOSTNAME ] ; then
- if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then
- EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp"
- elif ! [ -z $DB_SOCK_OR_PORT ] ; then
- EXTRA=" --socket=$DB_SOCK_OR_PORT"
- elif ! [ -z $DB_HOSTNAME ] ; then
- EXTRA=" --host=$DB_HOSTNAME --protocol=tcp"
- fi
- fi
-
- # create database
- mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA
-}
-
-install_wp
-install_test_suite
-install_db
diff --git a/composer.json b/composer.json
deleted file mode 100644
index 65d629a..0000000
--- a/composer.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "minimum-stability": "stable",
- "config": {
- "bin-dir": "bin",
- "vendor-dir": "vendor"
- },
- "require-dev": {
- "phpunit/phpunit": "4.1.*",
- "behat/behat": "2.5.3",
- "behat/behat": "2.5.3",
- "behat/mink": "1.5",
- "behat/mink-extension": "*",
- "behat/mink-goutte-driver": "*",
- "behat/mink-selenium2-driver": "*"
- }
-}
diff --git a/features/bootstrap/FeatureContext.php b/features/bootstrap/FeatureContext.php
deleted file mode 100644
index d615d33..0000000
--- a/features/bootstrap/FeatureContext.php
+++ /dev/null
@@ -1,67 +0,0 @@
-login($username, $password);
- }
-
- /**
- * @When /^I write a post with title "([^"]*)" and content "([^"]*)"$/
- */
- public function iWriteAPostWithTitleAndContent($post_title, $content)
- {
- $this->fill_in_post('post', $post_title, 'publish', $content);
- }
-
- /**
- * @Given /^the plugin "([^"]*)" is "([^"]*)"$/
- */
- public function thePluginIs($plugin, $state)
- {
- if ($state == "active") {
- $action = "activate";
- } else {
- $action = "deactivate";
- }
- shell_exec(escapeshellcmd("wp plugin $action $plugin"));
- }
-
- /**
- * @When /^I search for "([^"]*)"$/
- */
- public function iSearchFor($term)
- {
- return array(
- new When("I fill in \"s\" with \"$term\""),
- new When("I press \"searchsubmit\""),
- );
- }
-
-}
diff --git a/features/bootstrap/WordPressContext.php b/features/bootstrap/WordPressContext.php
deleted file mode 100644
index 130cecc..0000000
--- a/features/bootstrap/WordPressContext.php
+++ /dev/null
@@ -1,248 +0,0 @@
-base_url = $params['base_url'];
- $this->role_map = $params['role_map'];
- }
-
- /**
- * Given a list of usernames (user_login field), checks for every username
- * if they exist. Returns a list of the users that do not exist.
- *
- * @param array $users
- * @return array
- * @author Maarten Jacobs
- **/
- protected function check_users_exist(array $users) {
- $session = $this->getSession();
-
- // Check if the users exist, saving the inexistent users
- $inexistent_users = array();
- $this->visit( 'wp-admin/users.php' );
- $current_page = $session->getPage();
- foreach ($users as $username) {
- if (!$current_page->hasContent($username)) {
- $inexistent_users[] = $username;
- }
- }
-
- return $inexistent_users;
- }
-
- /**
- * Creates a user for every username given (user_login field).
- * The inner values can also maps of the following type:
- * array(
- * 'username' =>
- * 'password' => (default: pass)
- * 'email' => (default: username@test.dev)
- * 'role' => (default: checks rolemap, or 'subscriber')
- * )
- *
- * @param array $users
- * @author Maarten Jacobs
- **/
- protected function create_users(array $users) {
- $session = $this->getSession();
-
- foreach ($users as $username) {
- if (is_array($username)) {
- $name = $username['username'];
- $password = array_key_exists('password', $username) ? $username['password'] : 'pass';
- $email = array_key_exists('email', $username) ? $username['email'] : str_replace(' ', '_', $name) . '@test.dev';
- } else {
- $name = $username;
- $password = 'pass';
- $email = str_replace(' ', '_', $name) . '@test.dev';
- }
-
- $this->visit( 'wp-admin/user-new.php' );
- $current_page = $session->getPage();
-
- // Fill in the form
- $current_page->findField('user_login')->setValue($name);
- $current_page->findField('email')->setValue($email);
- $current_page->findField('pass1')->setValue($password);
- $current_page->findField('pass2')->setValue($password);
-
- // Set role
- $role = ucfirst( strtolower( $this->role_map[$name] ) );
- $current_page->findField('role')->selectOption($role);
-
- // Submit form
- $current_page->findButton('Add New User')->click();
- }
- }
-
- /**
- * Fills in the form of a generic post.
- * Given the status, will either publish or save as draft.
- *
- * @param string $post_type
- * @param string $post_title
- * @param string $status Either 'draft' or anything else for 'publish'
- * @author Maarten Jacobs
- **/
- protected function fill_in_post($post_type, $post_title, $status = 'publish', $content = '
Testing all the things. All the time.
') {
- // The post type, if not post, will be appended.
- // Rather than a separate page per type, this is how WP works with forms for separate post types.
- $uri_suffix = $post_type !== 'post' ? '?post_type=' . $post_type : '';
- $this->visit( 'wp-admin/post-new.php' . $uri_suffix );
- $session = $this->session = $this->getSession();
- $current_page = $session->getPage();
-
- // Fill in the title
- $current_page->findField( 'post_title' )->setValue( $post_title );
- // Fill in some nonsencical data for the body
- // clickLink and setValue seem to be failing for TinyMCE (same for Cucumber unfortunately)
- $session->executeScript( 'jQuery( "#content-html" ).click()' );
- $session->executeScript( 'jQuery( "#content" ).val( "' . $content . '" )' );
-
- // Click the appropriate button depending on the given status
- $state_button = 'Save Draft';
- switch ($status) {
- case 'draft':
- // We're good.
- break;
-
- case 'publish':
- default:
- // Save as draft first
- $current_page->findButton($state_button)->click();
- $state_button = 'Publish';
- break;
- }
- $current_page->findButton($state_button)->click();
- // go to view of new post
- $session->getPage()->clickLink("View $post_type");
- }
-
- /**
- * Makes sure the current user is logged out, and then logs in with
- * the given username and password.
- *
- * @param string $username
- * @param string $password
- * @author Maarten Jacobs
- **/
- protected function login($username, $password = 'pass') {
- $session = $this->session = $this->getSession();
- $current_page = $session->getPage();
-
- // Check if logged in as that user
- $this->visit( 'wp-admin' );
- if ($current_page->hasContent( "Howdy, {$username}" )) {
- // We're already logged in as this user.
- // Double-check
- $this->assertPageContainsText('Dashboard');
- return true;
- }
-
- // Logout
- $this->visit( 'wp-login.php?action=logout' );
- if ($session->getPage()->hasLink('log out')) {
- $session->getPage()->clickLink('log out');
- $current_page = $session->getPage();
- }
-
- // And login
- $current_page->fillField('user_login', $username);
- $current_page->fillField('user_pass', $password);
- $current_page->findButton('wp-submit')->click();
-
- // Assert that we are on the dashboard
- $this->assertPageContainsText('Dashboard');
- }
-
- /**
- * Given the current page is post list page, we enter the title in the searchbox
- * and search for that post.
- *
- * @param string $post_title The title of the post as it would appear in the WP backend
- * @param boolean $do_assert If set to anything but false, will assert for the existence of the post title after the search
- * @return void
- * @author Maarten Jacobs
- **/
- protected function searchForPost( $post_title, $do_assert = FALSE ) {
-
- $current_page = $this->getSession()->getPage();
-
- // Search for the post
- $search_field = $current_page->findField( 'post-search-input' ); // Searching on #id
- // When there is no content, then the searchbox is not shown
- // So we skip search in that case
- if ($search_field) {
- $search_field->setValue( $post_title );
-
- $current_page->findField( 'Search Posts' ) // Searching on value
- ->click();
- }
-
- // We don't stop tests even if the searchbox does not exist.
- // That would prevent the dev from knowing what the hell's going on.
- // Can I assert all the things?
- if ( $do_assert ) {
- $this->assertPageContainsText($post_title);
- }
-
- }
-
- /**
- * @Given /^I trash the "([^"]*)" titled "([^"]*)"$/
- */
- public function iTrashThePostTitled( $post_type, $post_title ) {
-
- $session = $this->session = $this->getSession();
-
- // Visit the posts page
- $uri_suffix = $post_type !== 'post' ? '?post_type=' . $post_type : '';
- $postlist_uri = 'wp-admin/edit.php' . $uri_suffix;
- $this->visit( $postlist_uri );
- $current_page = $session->getPage();
-
- // Check if the post with that title is on the current page
- if (!$current_page->hasContent( $post_title )) {
- // If not, search for the post
- $this->searchForPost( $post_title );
- }
- $this->assertPageContainsText($post_title);
-
- // Select the post in the checkbox column
- // This is tricky: the checkbox has a non-unique name (of course, that's the way to do it)
- // So we need to check the box in a different way
- // The easiest: jQuery
- $session->executeScript( "jQuery( \"tr:contains('$post_title') :checkbox\" ).click()" );
-
- // Trash it
- // - Select the 'Move to Trash' option
- $current_page->selectFieldOption( 'action', 'Move to Trash' );
- // - Click to Apply
- $current_page->findButton( 'doaction' )->click();
-
- // Check if the post is no longer visible on the posts page
- $this->visit( $postlist_uri );
- $this->assertPageNotContainsText( $post_title );
- // Make a search, because it could be on another page
- $this->searchForPost( $post_title );
- $this->assertPageNotContainsText( $post_title );
-
- }
-
-}
diff --git a/features/shortcodes.feature b/features/shortcodes.feature
deleted file mode 100644
index 28df0fd..0000000
--- a/features/shortcodes.feature
+++ /dev/null
@@ -1,21 +0,0 @@
-Feature: Use Shortcodes
- In order to use my Plugin
- As a website author
- I need to write posts with shortcodes
-
- Background:
- Given I am logged in as "admin" with "vagrant"
-
- Scenario: Without the plugin
- Given the plugin "freifunkmeta" is "inactive"
- When I write a post with title "test" and content "[ff_contact]"
- #Then print current URL
- Then I should see "ff_contact"
-
- Scenario: With the plugin
- Given the plugin "freifunkmeta" is "active"
- When I write a post with title "test" and content "[ff_contact]"
- #Then print current URL
- Then I should see "Twitter" in the ".ff_contact" element
- And I should not see "ff_contact"
-
diff --git a/features/wp-search.feature b/features/wp-search.feature
deleted file mode 100644
index 879e7d8..0000000
--- a/features/wp-search.feature
+++ /dev/null
@@ -1,10 +0,0 @@
-Feature: Search
- In order to find older articles
- As a website user
- I need to be able to search for a word
-
- Scenario: Searching for a post
- Given I am on the homepage
- When I search for "Welcome"
- Then I should see "Hello world!"
- And I should see "Welcome to WordPress. This is your first post."
diff --git a/freifunk_marker.png b/freifunk_marker.png
deleted file mode 100644
index 279c962..0000000
Binary files a/freifunk_marker.png and /dev/null differ
diff --git a/freifunkmeta.php b/freifunkmeta.php
index ca39e8e..e6d0f4e 100644
--- a/freifunkmeta.php
+++ b/freifunkmeta.php
@@ -1,536 +1,158 @@
false );
- $http_response = wp_remote_get( $url, $args );
- if ( is_wp_error( $http_response ) ) {
- $error_msg = sprintf(
- 'Unable to retrieve URL %s, error: %s',
- $url, $http_response->get_error_message()
- );
- error_log( $error_msg, 4 );
- return $http_response;
- } else {
- $json = wp_remote_retrieve_body( $http_response );
- $data = json_decode( $json, $assoc = true );
- set_transient( $cachekey, $data, $cachetime );
- }
- }
- return $data;
- }
+/* gets metadata from URL, handles caching */
+function ff_meta_getmetadata ($url) {
+ $url_hash = hash('crc32', $url);
+
+ // Caching
+ if ( false === ( $metajson = get_transient( "ff_metadata_${url_hash}" ) ) ) {
+ $metajson = wp_remote_retrieve_body( wp_remote_get($url) );
+ set_transient( "ff_metadata_${url_hash}", $metajson, 1 * HOUR_IN_SECONDS );
+ }
+ $metadata = json_decode ( $metajson, $assoc = true );
+ return $metadata;
}
-/**
- * holds the community directory
- */
-class FF_Directory
-{
- private $directory;
- private $ed;
+if ( ! shortcode_exists( 'ff_services' ) ) {
+ add_shortcode( 'ff_services', 'ff_meta_shortcode_services');
+}
+// Example:
+// [ff_services]
+// [ff_services url="http://meta.hamburg.freifunk.net/ffhh.json"]
+function ff_meta_shortcode_services( $atts ) {
+ $default_url = get_option( 'ff_meta_url' );
+ extract(shortcode_atts( array(
+ 'url' => $default_url,
+ ), $atts));
- function __construct( $ext_data_service = null ) {
- if ( is_null( $ext_data_service ) ) {
- $this->ed = new FF_Meta_Externaldata();
- } else {
- $this->ed = $ext_data_service;
- }
- $data = $this->ed->get( FF_META_DEFAULT_DIR );
- if ( is_wp_error( $data ) ) {
- $this->directory = array();
- } else {
- $this->directory = $data;
- }
- }
+ $metadata = ff_meta_getmetadata ($url);
+ $services = $metadata['services'];
- function get_url_by_city( $city ) {
- if ( array_key_exists( $city, $this->directory ) ) {
- return $this->directory[$city];
- } else {
- return false;
- }
- }
-
- // get one big array of all known community data
- function get_all_data() {
- $all_locs = array();
- foreach ( $this->directory as $tmp_city => $url ) {
- $tmp_meta = $this->ed->get( $url );
- if ( ! is_wp_error( $tmp_meta ) ) {
- $all_locs[$tmp_city] = $tmp_meta;
- }
- }
- return $all_locs;
- }
+ // Output
+ $outstr = '
',
- $this->name, $this->street, $this->zip, $this->city
- );
- }
+ // Output -- rather ugly but the data is not uniform, some fields are URIs, some are usernames, ...
+ $outstr = '
';
- return $outstr;
- }
-
- function admin_menu() {
- // Options Page:
- add_options_page(
- 'FF Meta Plugin', // page title
- 'FF Meta', // menu title
- 'manage_options', // req'd capability
- 'ff_meta_plugin', // menu slug
- array( 'FF_meta', 'options_page' ) // callback function
- );
- }
-
- function admin_init() {
- register_setting(
- 'ff_meta_settings-group', // group name
- 'ff_meta_cachetime' // option name
- );
- register_setting(
- 'ff_meta_settings-group', // group name
- 'ff_meta_city' // option name
- );
- add_settings_section(
- 'ff_meta_section-one', // ID
- 'Section One', // Title
- 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
- 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
- );
- add_settings_field(
- 'ff_meta_cachetime', // ID
- 'Cache time', // Title
- 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 section_one_callback() {
- echo 'This Plugin provides shortcodes to display information'
- .' from the Freifunk meta.json.';
- }
-
- function cachetime_callback() {
- $time = get_option( 'ff_meta_cachetime', FF_META_DEFAULT_CACHETIME );
- echo 'Data from external URLs is cached'
- .' for this number of minutes.