From 565a29898672674252b1d824001ed34c6563f0f6 Mon Sep 17 00:00:00 2001 From: bozdoz Date: Fri, 21 Apr 2023 00:14:05 -0300 Subject: [PATCH 1/8] moves geocoders to use single transient key --- .vscode/settings.json | 3 -- class.geocoder.php | 99 ++++++++++++++++++++++++++++--------------- docker-compose.yml | 8 ++++ 3 files changed, 74 insertions(+), 36 deletions(-) delete mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index ad92582..0000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "editor.formatOnSave": true -} diff --git a/class.geocoder.php b/class.geocoder.php index 6bfebc3..d467468 100644 --- a/class.geocoder.php +++ b/class.geocoder.php @@ -23,6 +23,11 @@ class Leaflet_Geocoder { */ public $lng = 0; + /** + * transients key for all locations + */ + public $locations_key = 'leaflet_geocoded_locations'; + /** * new Geocoder from address * @@ -39,10 +44,10 @@ public function __construct ($address) { $geocoder = $settings->get('geocoder'); - $cached_address = 'leaflet_' . $geocoder . '_' . $address; + $cached_address = $geocoder . '_' . $address; /* retrieve cached geocoded location */ - $found_cache = get_option( $cached_address ); + $found_cache = $this->get_cache( $cached_address ); if ( $found_cache ) { $location = $found_cache; @@ -53,13 +58,8 @@ public function __construct ($address) { try { $location = (Object) $this->$geocoding_method( $address ); - /* add location */ - add_option($cached_address, $location); - - /* add option key to locations for clean up purposes */ - $locations = get_option('leaflet_geocoded_locations', array()); - array_push($locations, $cached_address); - update_option('leaflet_geocoded_locations', $locations); + /* update location data in db/cache */ + $this->set_cache($cached_address, $location); } catch (Exception $e) { // failed $location = $this->not_found; @@ -72,17 +72,6 @@ public function __construct ($address) { } } - /** - * Removes location caches - */ - public static function remove_caches () { - $addresses = get_option('leaflet_geocoded_locations', array()); - foreach ($addresses as $address) { - delete_option($address); - } - delete_option('leaflet_geocoded_locations'); - } - /** * Used by geocoders to make requests via curl or file_get_contents * @@ -95,13 +84,12 @@ private function get_url( $url ) { $referer = get_site_url(); if (in_array('curl', get_loaded_extensions())) { - /* try curl */ $ch = curl_init(); curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE); curl_setopt($ch, CURLOPT_HEADER, 0); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_REFERER, $referer); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_REFERER, $referer); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); @@ -110,14 +98,12 @@ private function get_url( $url ) { return $data; } else if (ini_get('allow_url_fopen')) { - /* try file get contents */ - - $opts = array( - 'http' => array( - 'header' => array("Referer: $referer\r\n") - ) - ); - $context = stream_context_create($opts); + $opts = array( + 'http' => array( + 'header' => array("Referer: $referer\r\n") + ) + ); + $context = stream_context_create($opts); return file_get_contents($url, false, $context); } @@ -132,7 +118,6 @@ private function get_url( $url ) { * @param string $address the urlencoded address to look up * @return varies object from API or null (failed) */ - private function google_geocode ( $address ) { // Leaflet_Map_Plugin_Settings $settings = Leaflet_Map_Plugin_Settings::init(); @@ -161,7 +146,6 @@ private function google_geocode ( $address ) { * @param string $address the urlencoded address to look up * @return varies object from API or null (failed) */ - private function osm_geocode ( $address ) { $geocode_url = 'https://nominatim.openstreetmap.org/?format=json&limit=1&q='; $geocode_url .= $address; @@ -198,4 +182,53 @@ private function dawa_geocode ( $address ) { 'lng' => $json[0]->adgangsadresse->adgangspunkt->koordinater[0] ); } + + /** + * Returns the single array of locations from transients + * @since v3.4.0 + */ + public function get_all_cached() { + // locations will be an array of address -> coordinates + if ( false === ($locations = get_transient( $this->locations_key )) ) { + return array(); + } + + return $locations; + } + + /** + * gets a single location's coordinates from the cached locations + * @since v3.4.0 + */ + public function get_cache($key) { + $locations = $this->get_all_cached(); + + return isset($locations[ $key ]) ? $locations[ $key ] : false; + } + + /** + * gets the array of saved locations and updates an individual location + * @since v3.4.0 + */ + public function set_cache($key, $value) { + $locations = $this->get_all_cached(); + + $locations[ $key ] = $value; + + return set_transient( $this->locations_key, $locations, MONTH_IN_SECONDS ); + } + + /** + * Removes location caches + */ + public static function remove_caches () { + + // removes legacy location db entries + $addresses = get_option('leaflet_geocoded_locations', array()); + foreach ($addresses as $address) { + delete_option($address); + } + delete_option('leaflet_geocoded_locations'); + } + } \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index ecc18b8..fb139a7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -58,6 +58,14 @@ services: WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DEBUG: 1 + # phpmyadmin: + # image: phpmyadmin + # restart: always + # ports: + # - 8080:80 + # environment: + # - PMA_ARBITRARY=1 + volumes: wp_db: wordpress: From 1d237492beafdee037ac019017b653bf1daa26f3 Mon Sep 17 00:00:00 2001 From: bozdoz Date: Fri, 21 Apr 2023 00:18:26 -0300 Subject: [PATCH 2/8] deletes transients on cleanup --- class.geocoder.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/class.geocoder.php b/class.geocoder.php index d467468..b954b99 100644 --- a/class.geocoder.php +++ b/class.geocoder.php @@ -185,7 +185,7 @@ private function dawa_geocode ( $address ) { /** * Returns the single array of locations from transients - * @since v3.4.0 + * @since 3.4.0 */ public function get_all_cached() { // locations will be an array of address -> coordinates @@ -198,7 +198,7 @@ public function get_all_cached() { /** * gets a single location's coordinates from the cached locations - * @since v3.4.0 + * @since 3.4.0 */ public function get_cache($key) { $locations = $this->get_all_cached(); @@ -208,7 +208,7 @@ public function get_cache($key) { /** * gets the array of saved locations and updates an individual location - * @since v3.4.0 + * @since 3.4.0 */ public function set_cache($key, $value) { $locations = $this->get_all_cached(); @@ -222,8 +222,11 @@ public function set_cache($key, $value) { * Removes location caches */ public static function remove_caches () { + // @since 3.4.0 + delete_transient( $this->locations_key ); // removes legacy location db entries + // pre 3.4.0 $addresses = get_option('leaflet_geocoded_locations', array()); foreach ($addresses as $address) { delete_option($address); From 4c70c7065a4877451a40a73e48b677a1a90b2d92 Mon Sep 17 00:00:00 2001 From: bozdoz Date: Mon, 24 Apr 2023 23:56:50 -0300 Subject: [PATCH 3/8] adds filters instead of transients; makes the plugin more pluggable --- class.geocoder.php | 102 ++++++++++++++++++++++++++------------------- 1 file changed, 60 insertions(+), 42 deletions(-) diff --git a/class.geocoder.php b/class.geocoder.php index b954b99..ace6665 100644 --- a/class.geocoder.php +++ b/class.geocoder.php @@ -11,7 +11,7 @@ class Leaflet_Geocoder { * Geocoder should return this on error/not found * @var array $not_found */ - private $not_found = array('lat' => 0, 'lng' => 0); + private static $not_found = array('lat' => 0, 'lng' => 0); /** * Latitude * @var float $lat @@ -23,10 +23,8 @@ class Leaflet_Geocoder { */ public $lng = 0; - /** - * transients key for all locations - */ - public $locations_key = 'leaflet_geocoded_locations'; + /** key for all locations */ + public static $locations_key = 'leaflet_geocoded_locations'; /** * new Geocoder from address @@ -44,10 +42,10 @@ public function __construct ($address) { $geocoder = $settings->get('geocoder'); - $cached_address = $geocoder . '_' . $address; + $cached_address = 'leaflet_' . $geocoder . '_' . $address; /* retrieve cached geocoded location */ - $found_cache = $this->get_cache( $cached_address ); + $found_cache = $this->get_cache( $cached_address, $address ); if ( $found_cache ) { $location = $found_cache; @@ -59,10 +57,13 @@ public function __construct ($address) { $location = (Object) $this->$geocoding_method( $address ); /* update location data in db/cache */ - $this->set_cache($cached_address, $location); + $this->set_cache( $cached_address, $location ); + + /* add cache to cached list for cleanup */ + $this->update_caches( $cached_address ); } catch (Exception $e) { // failed - $location = $this->not_found; + $location = self::$not_found; } } @@ -131,7 +132,6 @@ private function google_geocode ( $address ) { /* found location */ if ($json->status == 'OK') { - $location = $json->results[0]->geometry->location; return (Object) $location; @@ -184,54 +184,72 @@ private function dawa_geocode ( $address ) { } /** - * Returns the single array of locations from transients - * @since 3.4.0 + * gets a single location's coordinates from the cached locations */ - public function get_all_cached() { - // locations will be an array of address -> coordinates - if ( false === ($locations = get_transient( $this->locations_key )) ) { - return array(); + public function get_cache($address_key, $plain_address) { + /** + * @since 3.4.0 + * using 'leaflet_geocoder_get_cache', + * you can return any value that is not identical to the address_key to avoid using get_option + */ + $filtered = apply_filters( 'leaflet_geocoder_get_cache', $address_key, $plain_address ); + + if ($filtered === $address_key) { + return get_option( $address_key ); } - return $locations; - } - - /** - * gets a single location's coordinates from the cached locations - * @since 3.4.0 - */ - public function get_cache($key) { - $locations = $this->get_all_cached(); - - return isset($locations[ $key ]) ? $locations[ $key ] : false; + return $filtered; } /** * gets the array of saved locations and updates an individual location - * @since 3.4.0 */ public function set_cache($key, $value) { - $locations = $this->get_all_cached(); - - $locations[ $key ] = $value; + /** + * @since 3.4.0 + * using 'leaflet_geocoder_set_cache', + * you can return any falsy value to omit the update_option + */ + if (apply_filters('leaflet_geocoder_set_cache', $key, $value)) { + update_option( $key, $value, false ); + } + } - return set_transient( $this->locations_key, $locations, MONTH_IN_SECONDS ); + /** + * Appends an address to a list of addresses in the db, for cleanup + */ + public function update_caches( $address ) { + /** + * @since 3.4.0 + * using 'leaflet_geocoder_update_caches', + * you can return any falsy value to omit the update_option + */ + if (apply_filters('leaflet_geocoder_update_caches', $address)) { + $locations = get_option( self::$locations_key, array() ); + + array_push( $locations, $address ); + + update_option( self::$locations_key, $locations, false ); + } } /** - * Removes location caches + * Removes all location caches */ - public static function remove_caches () { - // @since 3.4.0 - delete_transient( $this->locations_key ); + public static function remove_caches() { + /** @since 3.4.0 */ + do_action('leaflet_remove_caches'); + + $addresses = get_option( self::$locations_key, array() ); + + if ( !$addresses ) { + return; + } - // removes legacy location db entries - // pre 3.4.0 - $addresses = get_option('leaflet_geocoded_locations', array()); foreach ($addresses as $address) { - delete_option($address); + delete_option( $address ); } - delete_option('leaflet_geocoded_locations'); - } + delete_option( self::$locations_key ); + } } \ No newline at end of file From 7baf8a6492a04c16f3e50cdf755d77a7ef798bd5 Mon Sep 17 00:00:00 2001 From: bozdoz Date: Tue, 25 Apr 2023 20:23:05 -0300 Subject: [PATCH 4/8] adds not_found filter --- class.geocoder.php | 9 ++++++--- shortcodes/class.map-shortcode.php | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/class.geocoder.php b/class.geocoder.php index ace6665..e4349ea 100644 --- a/class.geocoder.php +++ b/class.geocoder.php @@ -62,8 +62,11 @@ public function __construct ($address) { /* add cache to cached list for cleanup */ $this->update_caches( $cached_address ); } catch (Exception $e) { - // failed - $location = self::$not_found; + /** + * @since 3.4.0 + * use 'leaflet_geocoder_not_found' filter to return your own not_found response + */ + $location = apply_filters( 'leaflet_geocoder_not_found', self::$not_found ); } } @@ -238,7 +241,7 @@ public function update_caches( $address ) { */ public static function remove_caches() { /** @since 3.4.0 */ - do_action('leaflet_remove_caches'); + do_action('leaflet_geocoder_remove_caches'); $addresses = get_option( self::$locations_key, array() ); diff --git a/shortcodes/class.map-shortcode.php b/shortcodes/class.map-shortcode.php index 0a1ee60..453f8fa 100644 --- a/shortcodes/class.map-shortcode.php +++ b/shortcodes/class.map-shortcode.php @@ -256,6 +256,7 @@ protected function getHTML($atts='', $content=null) if (!empty($address)) { /* try geocoding */ include_once LEAFLET_MAP__PLUGIN_DIR . 'class.geocoder.php'; + // TODO: should this be a try/catch? $location = new Leaflet_Geocoder($address); $lat = $location->lat; $lng = $location->lng; From b6a704281ee165bac6062c7c7ed08bfbade0eabe Mon Sep 17 00:00:00 2001 From: bozdoz Date: Tue, 25 Apr 2023 21:22:35 -0300 Subject: [PATCH 5/8] osm is default --- class.geocoder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class.geocoder.php b/class.geocoder.php index e4349ea..eece33d 100644 --- a/class.geocoder.php +++ b/class.geocoder.php @@ -2,7 +2,7 @@ /** * Geocoder * -* calls the specific geocoder function (chosen in admin or default: google_geocode) +* calls the specific geocoder function (chosen in admin or default: osm) * */ From c95a0dee6ceb13b6ba322430eb8ee292e898823e Mon Sep 17 00:00:00 2001 From: bozdoz Date: Wed, 17 May 2023 23:39:30 -0300 Subject: [PATCH 6/8] adds migration; resolves #222 --- class.geocoder.php | 37 ++++++++++++----- class.leaflet-map.php | 28 +++++++++++-- class.migrations.php | 40 +++++++++++++++++++ leaflet-map.php | 10 ++--- migrations/001-v3.4.0-geocoder-transients.php | 37 +++++++++++++++++ shortcodes/class.map-shortcode.php | 1 + shortcodes/class.shortcode.php | 1 + 7 files changed, 136 insertions(+), 18 deletions(-) create mode 100644 class.migrations.php create mode 100644 migrations/001-v3.4.0-geocoder-transients.php diff --git a/class.geocoder.php b/class.geocoder.php index eece33d..feba05b 100644 --- a/class.geocoder.php +++ b/class.geocoder.php @@ -193,12 +193,12 @@ public function get_cache($address_key, $plain_address) { /** * @since 3.4.0 * using 'leaflet_geocoder_get_cache', - * you can return any value that is not identical to the address_key to avoid using get_option + * you can return any value that is not identical to the address_key to avoid using get_transient */ $filtered = apply_filters( 'leaflet_geocoder_get_cache', $address_key, $plain_address ); if ($filtered === $address_key) { - return get_option( $address_key ); + return get_transient( $address_key ); } return $filtered; @@ -211,10 +211,21 @@ public function set_cache($key, $value) { /** * @since 3.4.0 * using 'leaflet_geocoder_set_cache', - * you can return any falsy value to omit the update_option + * you can return any falsy value to omit the set_transient */ if (apply_filters('leaflet_geocoder_set_cache', $key, $value)) { - update_option( $key, $value, false ); + // get user-defined expiry (maybe this should be an admin option?) + $expiry = apply_filters('leaflet_geocoder_expiry', null); + + if ($expiry === null) { + // stagger caches between 200-400 days to prevent all caches expiring on the same day + $stagger = random_int(200, 400); + $expiry = DAY_IN_SECONDS * $stagger; + $output = "
$expiry
"; + file_put_contents(LEAFLET_MAP__PLUGIN_DIR . 'log.log', $output, FILE_APPEND); + } + + set_transient( $key, $value, $expiry ); } } @@ -225,14 +236,20 @@ public function update_caches( $address ) { /** * @since 3.4.0 * using 'leaflet_geocoder_update_caches', - * you can return any falsy value to omit the update_option + * you can return any falsy value to omit the set_transient */ if (apply_filters('leaflet_geocoder_update_caches', $address)) { - $locations = get_option( self::$locations_key, array() ); + $locations = get_transient( self::$locations_key ); + + if (!$locations) { + $locations = array(); + } array_push( $locations, $address ); - update_option( self::$locations_key, $locations, false ); + // set to 25 year expiry since we never really want it to expire + // but omitting expiry causes it to autoload + set_transient( self::$locations_key, $locations, YEAR_IN_SECONDS * 25 ); } } @@ -243,16 +260,16 @@ public static function remove_caches() { /** @since 3.4.0 */ do_action('leaflet_geocoder_remove_caches'); - $addresses = get_option( self::$locations_key, array() ); + $addresses = get_transient( self::$locations_key ); if ( !$addresses ) { return; } foreach ($addresses as $address) { - delete_option( $address ); + delete_transient( $address ); } - delete_option( self::$locations_key ); + delete_transient( self::$locations_key ); } } \ No newline at end of file diff --git a/class.leaflet-map.php b/class.leaflet-map.php index 5c36ac5..55b5d9f 100644 --- a/class.leaflet-map.php +++ b/class.leaflet-map.php @@ -104,6 +104,7 @@ public static function init() { * Leaflet_Map Constructor */ private function __construct() { + $this->run_migrations(); $this->init_hooks(); $this->add_shortcodes(); @@ -111,6 +112,26 @@ private function __construct() { do_action('leaflet_map_loaded'); } + /** + * Check for version discrepancy and run migrations if necessary + * @since 3.4.0 + */ + private function run_migrations() { + // assume 3.3.0 if it doesn't exist + $db_version = get_option(LEAFLET_MAP__DB_VERSION_KEY, '3.3.0'); + + if ($db_version === LEAFLET_MAP__PLUGIN_VERSION) { + return; + } + + include_once LEAFLET_MAP__PLUGIN_DIR . 'class.migrations.php'; + + Leaflet_Map_Migrations::run_once($db_version); + + // set db version to current plugin version + update_option(LEAFLET_MAP__DB_VERSION_KEY, LEAFLET_MAP__PLUGIN_VERSION); + } + /** * Add actions and filters */ @@ -187,8 +208,8 @@ public static function enqueue_and_register() $js_url = $settings->get('js_url'); $css_url = $settings->get('css_url'); - wp_register_style('leaflet_stylesheet', $css_url, Array(), null, false); - wp_register_script('leaflet_js', $js_url, Array(), null, true); + wp_register_style('leaflet_stylesheet', $css_url, Array(), LEAFLET_MAP__PLUGIN_VERSION, false); + wp_register_script('leaflet_js', $js_url, Array(), LEAFLET_MAP__PLUGIN_VERSION, true); // new required MapQuest javascript file $tiling_service = $settings->get('default_tiling_service'); @@ -204,7 +225,8 @@ public static function enqueue_and_register() // optional ajax geojson plugin wp_register_script('tmcw_togeojson', $settings->get('togeojson_url'), Array('jquery'), LEAFLET_MAP__PLUGIN_VERSION, false); - if (defined('WP_DEBUG') && WP_DEBUG) { + // @since 3.4.0 + if (defined('LEAFLET_MAP__DEBUG') && LEAFLET_MAP__DEBUG) { $minified = ''; } else { $minified = '.min'; diff --git a/class.migrations.php b/class.migrations.php new file mode 100644 index 0000000..3c244fb --- /dev/null +++ b/class.migrations.php @@ -0,0 +1,40 @@ +