Saving/Changing Style ID

Saving/changing the Style ID (Smart Option: style_id) is what applies the pre-made styles from the Style Server (running on the main SLP site at the moment).

\SLP_SmartOptions::view_appearance()

This method defines the Smart Option for style_id.
It is a hidden field (changed with JS on the old Settings | View interface).
When changed it calls \SLP_SmartOptions::change_style_id() which directly calls \SLP_Style_Manager->change_style() to load the style changes from the style server.

This also sets up related style Smart Option which displays the “style_vision_list” vue based listing.

The now-defunct theme Smart Option is also set, but this is for legacy support and no longer used.

			$smart_options['theme']    = array(
				'type'    => 'hidden',
				'default' => 'a_gallery_style',
			);
			$smart_options['style_id'] = array(
				'type'              => 'hidden',
				'call_when_changed' => array( $this, 'change_style_id' ),
			);
			$smart_options['style']    = array(
				'type'       => 'style_vision_list',
				'show_label' => true,
				'wrapper'    => false,
				'vue'        => true,
			);
			$smart_

\SLP_Style_Manager::change_style_id()

Call stack when clicking “select style” on the legacy “style vision list”:

SLP_SmartOptions.php:320, SLP_SmartOptions->change_style_id()
SLP_SmartOptions.php:539, SLP_SmartOptions->execute_change_callbacks()
SLP_Admin_Settings.php:409, SLP_Admin_Settings->save_options()
SLP_Admin_UI.php:538, SLP_Admin_UI->setup_admin_screen()
class-wp-hook.php:324, WP_Hook->apply_filters()
class-wp-hook.php:348, WP_Hook->do_action()
plugin.php:517, do_action()
class-wp-screen.php:424, WP_Screen->set_current_screen()
screen.php:243, set_current_screen()
admin.php:212, {main}()

Call stack when clicking “activate” on the new style manager (React based) interface:

SLP_SmartOptions.php:320, SLP_SmartOptions->change_style_id()
SLP_SmartOptions.php:539, SLP_SmartOptions->execute_change_callbacks()
SLP_REST_Handler.php:719, SLP_REST_Handler->update_smart_option()
MySLP.php:266, MySLP->rest_dispatch_request_filter()
class-wp-hook.php:324, WP_Hook->apply_filters()
plugin.php:205, apply_filters()
class-wp-rest-server.php:1187, WP_REST_Server->respond_to_request()
class-wp-rest-server.php:1041, WP_REST_Server->dispatch()
class-wp-rest-server.php:431, WP_REST_Server->serve_request()
rest-api.php:424, rest_api_loaded()
class-wp-hook.php:324, WP_Hook->apply_filters()
class-wp-hook.php:348, WP_Hook->do_action()
plugin.php:565, do_action_ref_array()
class-wp.php:418, WP->parse_request()
class-wp.php:813, WP->main()
functions.php:1336, wp()
wp-blog-header.php:16, require()
index.php:17, {main}()

Style Caching

Only the Style Vision list currently caches style info by setting a transient via \SLP_Style_Manager::cache_style(), it does this as it renders each style response returned from the style server while rendering the vision list.

The cache is kept for one week.

The current style comes from a transient that caches the style server responses.

An example entry:

stdClass Object
(
    [id] => 67
    [date] => 2023-02-21T13:38:51
    [date_gmt] => 2023-02-21T18:38:51
    [guid] => stdClass Object
        (
            [rendered] => http://3.211.25.112/?post_type=slp_style_gallery&p=67
        )

    [modified] => 2024-12-21T13:25:44
    [modified_gmt] => 2024-12-21T18:25:44
    [slug] => basic
    [status] => publish
    [type] => slp_style_gallery
    [link] => https://storelocatorplus.com/slp_style_gallery/basic/
    ...

\SLP_SmartOptions::style

This is the style vision list rendering.

This is also used to cache the style settings from the server by comparing \SLP_Style_Manager::current_style->slug versus the \SLP_SmartOptions::style value

Used By

  • \SLP_Style_Manager::style_matches_slug()
    • which is used by \SLP_Style_Manager::set_active_style()
      • which is used by \SLP_Style_Manager::apply_style()

\SLP_SmartOptions::style_id

The actual selected style_id.

Locator Style Architecture

This setting is stored in the options_nojs[‘style’] option setting.

It is managed by an instantiation of the SLP_Settings_style_vision_list object.

  • data_field: options_nojs[style]
  • label: ‘Locator Style’
  • type: ‘style_vision_list’

This is a “smart option” managed by SLP_SmartOptions.
It is defined in \SLP_SmartOptions:view_appearance()
It has a ‘vue’ object type for rendering assistance.

Stack Trace : SLP | Settings

Triggered selecting – Menu : Store Locator Plus® | Settings

Most recent to oldest…

  • SLP_Settings_card_list.php:42, SLP_Settings_card_list->display()
    • SLP_Settings_Group.php:88, SLP_Settings_Group->display()
      • SLP_Settings_Section.php:94, SLP_Settings_Section->display()
        • SLP_Settings.php:384, SLP_Settings->render_settings_page()
          • SLP_Admin_Settings.php:289, SLP_Admin_Settings->display()
  • SLP_Settings_style_vision_list.php:15, SLP_Settings_style_vision_list->get_items()
    • SLP_Settings_card_list.php:28, SLP_Settings_card_list->at_startup()
      • SLP_Setting.php:48, SLP_Setting->initialize()
        • SLP_Admin_Settings.php:213, SLP_Admin_Settings->add_view()

Showing The Currently Selected Style

\SLP_Settings_card_list::display()

Renders the list of styles.

When $this->value === $item->clean_title it marks it as selected.

$item is from the list of locator styles fetched from the SLP locator style service (see \SLP_Settings_style_vision_list->items below).

Stack Trace : setting the initial value of the ‘style’ property (option)

\SLP_Setting->set_value() appears to have value already set to “”.

Track down the SLP_SmartOptions and how it loads the default values from options/options_nojs into the Smart Option properties.

  • SLP_SmartOptions.php:1784, SLP_SmartOptions->set_valid_option()
    • SLP_SmartOptions.php:1832, SLP_SmartOptions->set_valid_options_nojs()
      • SLP_SmartOptions.php:1661, array_walk()
        • SLP_SmartOptions.php:1661, SLP_SmartOptions->slp_specific_setup()
          • SLP_SmartOptions.php:1513, SLP_SmartOptions->initialize_after_plugins_loaded() SLPlus.php:386
            • SLPlus->initialize_after_plugins_loaded()

Class : SLP_Setting

Methods

set_value()

Sets the value of a setting.

Fetches the value of a setting from \WPOption_Manager::get_wp_option() if necessary.

Class : SLP_Settings_card_list

Extends SLP_Setting.

SLP_Setting type: “style_vision_list”

Class: SLP_Settings_style_vision_list

Extends SLP_Settings_card_list.

Properties

items : SLP_Setting_item[]

Contains the array of styles retrieved from the SLP Locator Styles service (REST call to external service).

value

Contains the currently set/selected style for the user.

SaaS Hooks Calls

See Lance Cleveland’s WordPress Hooks Order Of Precedence.

Processing Modes

Base Loop

Generic WordPress + MySLP processing of a page request.

  • WordPress : muplugins_loaded
  • WordPress : registered_taxonomy
  • WordPress : registered_post_type
  • WordPress : plugins_loaded
  • WordPress : set_current_user
  • WordPress : init
    • SLP : slp_init_complete
      • SLP: start_slp_specific_setup
      • SLP: finish_slp_specific_setup
  • WordPress : parse_request
  • WordPress : rest_api_init
  • WordPress : send_headers

WordPress : plugins_loaded

Fires once activated plugins have loaded. The hook is generally used for immediate filter setup, or plugin overrides. The plugins_loaded action hook fires early, and precedes the setup_theme, after_setup_theme, init and wp_loaded action hooks.

Used By

  • MySLP_Dashboard_Controller :: load_hooks()
    • add_action( ‘plugins_loaded’, array( CLASS, ‘plugins_loaded’ ) );

WordPress : set_current_user

WordPress : init

Fires after WordPress has finished loading but before any headers are sent. Most of WP is loaded at this stage, and the user is authenticated.

Used By

  • Site_Architect::__construct()
    • add_action( ‘init’, array( $this, ‘sa_start_session’ ) );
  • SLP_Actions:initialize()
    • add_action( ‘init’, array( $this, ‘init’ ), 11 );

      Sets up the slplus->database object with slplus->database = SLP_Data::get_instance().
      This needs to happen AFTER the WoredPress:set_current_user is called so MySLP has the proper user meta to set the database attributes.
  • MySLP::add_hooks()
    • add_action( ‘init’, array( $this, ‘perform_init_actions’ ) );

User Logged In Traced Calls

  • Site_Architect::sa_start_session()
  • SLP_Actions::init()
  • MySLP::perform_init_actions()

SLP : slp_init_complete

Executed during WordPress : init hook via SLP_Actions::init() after all of the main SLP plugin init stuff has been executed.

Used By

  • \MySLP_Dashboard_Controller::load_hooks()
    • add_action( 'slp_init_complete', array( __CLASS__, 'slp_init_complete' ) );
  • SLP_BaseClass_Addon :: initialize()
    • add_action( ‘slp_init_complete’, array( $this, ‘slp_init’ ) );
  • SLP_Power_Pages :: add_hooks_and_filters()
    • add_action( ‘slp_init_complete’ , array( $this , ‘do_when_slp_ready’ ) , 11 ); // 11 ensures the base slp_init has run for the addon

WordPress : parse_request

Used By

  • WordPress : rest_api_loaded
    in wordpress/wp-includes/rest-api.php
    this eventually calls the REST custom endpoint permission_callback

WordPress : rest_api_init

Called when processing a REST API call.

slp_ajax_response

Used By

\SLP_Premier_AJAX::add_ajax_hooks()

Invoked By

\SLP_AJAX::renderJSON_Response()

slp_ajaxsql_fullquery

Used By

\SLP_Experience_AJAX::add_ajax_hooks()
\SLP_Premier_AJAX::add_ajax_hooks()

Invoked By

\SLP_AJAX::execute_location_query()

slp_rest_geocode_invalid_referer

Invoked By

\SLP_REST_Handler::valid_referer() for any site that is not coming from get_site_url() or get_home_url(). This is run via the WordPress REST API handler via the register_rest_route() for the readable request for geocoding at the wp-json/store-locator-plus/v2/geocode/<address> endpoint. This happens via the permission_callback property.

Updating Staging SaaS Server

This process is for updating the staging Store Locator Plus® SaaS server running on an ECS cluster after performing code updates.

These processes require a locally installed copy of the MySLP AWS ECS Kit repository which can be found at ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/myslp_aws_ecs_kit.

Edit your code or deployment kit files first. This can include WordPress plugins or themes, the Docker composer or image builder commands, helper scripts, or various configuration files used to manage and deploy the Store Locator Plus® SaaS container images.

Once your updates are ready, make sure the WordPress stack is up-to-date by updating the submodule links, then commit all of your updates to the MySLP AWS ECS Kit repository on the proper branch. There are AWS CodePipeline services running that will monitor the repository for changes, build any images as needed with ECR and deploy them via the Elastic Container Service if possible. Details on the processes are noted below.

Update The Submodules

From the MySLP AWS ECS Kit git project root:

./tools/create_mustuseplugins_stubs.sh

Commit The Code Updates To The Repo

Commit any changes to the MySLP AWS ECS Kit repository.

When you push the changes from your local develop, staging, or production branch an AWS listener service will detect the code changes and run Code Pipeline tied to services such as CodeBuild and ECS to deploy the final Store Locator Plus® SaaS container in the AWS cloud.

Commits to local branches will not trigger a change in the AWS deployments.

Commits to any branch not specifically named develop, staging, or production will not trigger changes in the AWS cloud deployments.

CodePipeline Notes

The CodePipeline that is configured to deploy the staging containers is named myslp-webserver-staging-pipeline.

Stage: Source

The pipeline monitors the staging branch on the AWS CodeCommit repo for the MySLP AWS ECS Kit project at ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/myslp_aws_ecs_kit

Stage: Build

The source will be read from the URL above and a series of commands will be executed in the cloud to create an container image. This image is stored in the AWS Elastic Container Registry as a private image.

The Store Locator Plus® SaaS (internal name: MySLP) container images are stored in the 744590032041.dkr.ecr.us-east-1.amazonaws.com/myslp2024-aarch64 docker image repository.

Staging branches will tag the latest build with the :staging tag.

Stage: Deploy

The deploy stage will execute if the build stage completes successfully. This stage will attempt to take the latest myslp2024-aarch64:staging ECR image and launch an active container in the AWS Elastic Container Service.

The deploy stage will attempt to launch a running container in the myslp-staging-cluster on the myslp-staging-service service within that cluster.

Manual Container Image Update

Build The Container Image and Store On AWS ECR

aws sso login --profile lance.cleveland

aws ecr get-login-password --region us-east-1 --profile lance.cleveland | docker login --username AWS --password-stdin 744590032041.dkr.ecr.us-east-1.amazonaws.com/myslp2024-aarch64

cd ./Docker/Images

docker build --platform=linux/arm64 -t 744590032041.dkr.ecr.us-east-1.amazonaws.com/myslp2024-aarch64:staging .
docker push 744590032041.dkr.ecr.us-east-1.amazonaws.com/myslp2024-aarch64:staging

SaaS Development / ECS Error establishing a database connection

Check The Server URL

For local development using composer the Docker/Composers/Secrets/docker-compose-rds-secrets.yml file will have the DB Host URL.

For ECS deployments the URL is in the Task Definition that is being run by the service. After updating the task you will want to deploy it to the ECS Service with Force Deployment and update the running service.

Check The Port

Newer database connections are not connecting on the default MySQL Port 3306 and instead use a different port. Newer systems use port 3309 for the development database server per the RDS database setup example.

Edit the Docker/Composers/Secrets/docker-compose-rds-secrets.yml file and add the port to the end:

SaaS Dev Setup

Copy Production Database To Development

Create a copy of the production database from to development on AWS RDS.

Update MySLP AWS ECS Kit RDS Secrets

This assumes you have a local copy of the AWS ECS Kit repo.

ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/myslp-dashboard

Edit Docker/Composers/Secrets/docker-compose-rds-secrets.yml.

Change the WORDPRESS_DB_HOST to the new AWS RDS endpoint.

Update The Docker Image

Update The Submodules

First update the submodule data and loader files by opening a terminal window at the MySLP AWS ECS Kit root directory.

./tools/create_mustuseplugins_stubs.sh

When this finishes, update this repo and push to origin and the AWS CodeCommit directory via git. 

This will ensure the new submodule list is updated on the ECR Docker Image for the SLP SaaS product.

Build The ECR Image

Validate The ECR Login

aws sso login --profile lance.cleveland
aws ecr get-login-password --region us-east-1 --profile lance.cleveland | docker login --username AWS --password-stdin 744590032041.dkr.ecr.us-east-1.amazonaws.com/myslp2024-aarch64

Build The Image

cd ./Docker/Images
docker build --platform=linux/arm64 -t 744590032041.dkr.ecr.us-east-1.amazonaws.com/myslp2024-aarch64:develop .

This image is built with a local wildcard certificate for *.storelocatorplus.com.

The domain names it can serve via Apache are defined in 000-default.conf which includes:
* local.storelocatorplus.com
* test.storelocatorplus.com
* dashbeta.storelocatorplus.com
* dashboard.storelocatorplus.com

Push The Image To AWS ECR

docker push 744590032041.dkr.ecr.us-east-1.amazonaws.com/myslp2024-aarch64:develop

Running Containers Locally

This kit will allow you to not only build the baseline Docker image for MySLP2024 on the ARM64 (aarch64) architecture but it also provides a mechanism for using that image to launch various test environments on your laptop via named projects running a WordPress and MySQL host.

The local execution is managed via the Docker Compose files in ./Docker/Composers all commands should be executed there. Start with this command:

cd ./Docker/Composers

MySLP2024 Baked In

All the code is baked into the myslp2024-aarch64 image.

Data is served from the AWS RDS Dev MySQL server.

docker compose -f docker-compose-myslp2024-core-dev.yml -f Secrets/docker-compose-rds-secrets.yml -p myslp2024_bakedin up -d

MySLP2024 Local Source

Ensures a copy of the WordPress 6.4.2 code is available for debug tracing in ./Guest/wordpress for inline debugging with xDebug.

Overwrites the SLP specific code files with locally mapped files mounted via Volumes.

Data is served from the AWS RDS Dev MySQL server.

docker compose -f docker-compose-myslp2024-core-dev.yml -f docker-compose-myslp2024-use-localsource.yml -f Secrets/docker-compose-rds-secrets.yml -p myslp2024_localsource up -d

Accessing The Docker Container

Add an entry into /etc/hosts on your local system like this:

Go to MySLP2024 Baked In

All the code is baked into the myslp2024-aarch64 image.

Data is served from the AWS RDS Dev MySQL server.

docker compose -f docker-compose-myslp2024-core-dev.yml -f Secrets/docker-compose-rds-secrets.yml -p myslp2024_bakedin up

MySLP2024 Local Source

Ensures a copy of the WordPress 6.4.2 code is available for debug tracing in ./Guest/wordpress for inline debugging with xDebug.

Overwrites the SLP specific code files with locally mapped files mounted via Volumes.

Data is served from the AWS RDS Dev MySQL server.

docker compose -f docker-compose-myslp2024-core-dev.yml -f docker-compose-myslp2024-use-localsource.yml -f Secrets/docker-compose-rds-secrets.yml -p myslp2024_localsource up

Accessing The Build

Add an entry to /etc/hosts

127.0.0.1 localhost dev.storelocatorplus.com local.storelocatorplus.com localwp.storelocatorplus.com kubernetes.docker.internal kubernetes.docker.internal

Surf to https://local.storelocatorplus.com/

Upgrade The Network

If the core WordPress database engine has been changed you may need to login as a super admin for the SaaS platform and upgrade the network to ensure all the blog sites (customer accounts) are updated to the latest data structures.

SmartOptions

Smart Options via the SLP_SmartOptions class (include/module/smartoptions/SLP_SmartOptions.php) handles nearly all of the settings (options in WordPress parlance) for the Store Locator Plus® plugin.

Methods

get_ValueOf( <property:string> )

Get the value of a Smart Option.

		
Check if a given property exists and return the value.		
@param string $property The property to check.
@return bool Returns true if the property exists and is not null, and its 'is_true' property is true. Otherwise, returns false.

is_true( <property:string)

Check if a given property is true.
@param string $property The property to check.
@return bool Returns true if the property exists and is not null, and its ‘is_true’ property is true. Otherwise, returns false.

if ( SLP_SmartOptions::get_instance()->is_true( 'use_territory_bounds' ) ) {
    $this->add_territory_bounds();
}

Store Locator Plus® Staging (Prerelease) Updates 2024 Edition

We are going to move away from manually-executed grunt tasks via the wp-dev-kit repository and move toward an AWS implemented solution. We are going to leverage AWS developer tools to get the job done.

The general process is that you work on code and merge it into the develop branch of the store-locator-plus repository on CodeCommit (the main upstream source). When that code is deemed “ready for testing” the repo manager will merge the develop branch into the staging branch for the repository. CodePipeline should see the change to the staging branch in the repo and fire off the build and deployment processes.

CodeCommit

The repo, and now official “source of truth” for the SLP code and build kit repositories.

ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/store-locator-plus

The “upstream” aws repo for Store Locator Plus®.

CodeBuild

The build manager that will compile , minify, clean, and otherwise manipulate the stuff in the main SLP repo and prepare it for release. In this case a staging release of the WordPress plugin .zip file.

CodePipeline

Watches the main SLP repo for changes on the staging branch and fires off the CodeBuild execution when that happens.

Our pipeline is the store-locator-plus-staging-release pipeline. It has 3 stages:

Source

The CodeCommit source noted above.

Build

The CodeBuild project noted above.

Note that the CodePipeline takes over the artifact generation output and will dump the final output artifact store-locator-plus.zip into a different CodePipeline specific bucket. This is NOT the same bucket that is specified in the CodeBuild configuration.

Deploy

This is a setting in CodePipeline, NOT a CodeDeploy project, that copies the output artifact (store-locator-plus.zip) from the private CodePipeline artifacts bucket over into the storelocatorplus/builds/staging bucket.

S3 Buckets

This process uses S3 buckets to store build and pipeline artifacts.

The deployment process uses a public web endpoint (HTTP, non-secure) to store the final output artifact alongside some other SLP “goodies”.

The AWS S3 SLP storage site is: http://storelocatorplus.s3-website-us-east-1.amazonaws.com/

This bucket contains an index.html that has been created “by hand” to link to the staging and production zip files.

Image by 🌼Christel🌼 from Pixabay

Debug: Results Phone Label Issue

Bug report

The Label for RESULTS PHONE is not appearing in front end

Recreation on QC

Set style on QC to “Default”.

Settings | Results | Results Layout:

<div id=”slp_results_[slp_location id]” class=”results_entry location_primary [slp_location featured]”> <div class=”results_row_left_column” id=”slp_left_cell_[slp_location id]” > [slp_addon section=primary position=first] <span class=”location_name”>[slp_location name] [slp_location uml_buttons] [slp_location gfi_buttons]</span> <span class=”location_distance”>[slp_location distance_1] [slp_location distance_unit]</span> [slp_addon section=primary position=last] </div> <div class=”results_row_center_column location_secondary” id=”slp_center_cell_[slp_location id]” > [slp_addon section=secondary position=first] <span class=”slp_result_address slp_result_street”>[slp_location address]</span> <span class=”slp_result_address slp_result_street2″>[slp_location address2]</span> <span class=”slp_result_address slp_result_citystatezip”>[slp_location city_state_zip]</span> <span class=”slp_result_address slp_result_country”>[slp_location country]</span> <div class=”contact_info”> <span class=”slp_result_address slp_result_phone”>[slp_location phone]</span> <span class=”slp_result_address slp_result_fax”>[slp_location fax]</span> </div> [slp_addon section=secondary position=last] </div> <div class=”results_row_right_column location_tertiary” id=”slp_right_cell_[slp_location id]” > [slp_addon section=tertiary position=first] <div class=”online_info”> <span class=”slp_result_contact slp_result_website”>[slp_location web_link]</span> <span class=”slp_result_contact slp_result_email”>[slp_location email_link]</span> <span class=”slp_result_contact slp_result_directions”><a href=”https://[slp_option map_domain]/maps?saddr=[slp_location search_address]&daddr=[slp_location location_address]” target=”_blank” class=”storelocatorlink”>[slp_location directions_text]</a></span> </div> <span class=”slp_result_contact slp_result_hours textblock”>[slp_location hours]</span> [slp_location pro_tags] [slp_location iconarray wrap=”fullspan”] [slp_location eventiconarray wrap=”fullspan”] [slp_location socialiconarray wrap=”fullspan”] [slp_addon section=tertiary position=last] </div> </div>

Settings | Results | Labels | Phone

Phone

Architecture: Update Plugin

FOR INTERNAL USE ONLY

The process that happens when a plugin is updated, especially the conversion of pre-existing options to SLPlus options / options_nojs serialized JSON objects.

In older releases , including some vestiges that still existing in 2209.X versions, options were stored in a WordPress option_name that match the plugin name. Such as option_name ‘slp-power’ for the power add on. Each add on had its own set of options.

When Smart Options were introduced into the SLP architecture there were two options that stored “all settings”. csl-slplus-options (aka “options”) stores settings that were not being localized and sent to JavaScript. csl-slplus-options_nojs (aka “options_nojs”) are the settings that are not localized. (In theory… both of these will be replaced with a single monolithic store in csl-slplus-options eventually and specific settings retrieved from JavaScript via a REST call).

The idea was to eventually (soon?) convert all separate plugin-specific option settings like option_name = ‘slp-power’ into a standard csl-slplus-options string. Below is the flowchart that describes how that conversion happens.