php_Settings.php

<?php
namespace FindStr;

class Settings {

  private object $settings;

  public array $post_types_to_index = array();

  public string $settings_save_file = 'findstr/settings.json';

  public string $settings_option_name = 'findstrSettings';

  public object $default_settings;

  protected static array $findstr_cached_settings = array();

  public function __construct() {

    /**
     * Filter the settings save path
     *
     * @hook findstr_settings_save_path
     *
     * @param {string} $settings_save_file
     * @param {string} $class_name
     *
     * @return {string} $settings_save_file
     */
    $this->settings_save_file = apply_filters( 'findstr_settings_save_path', trailingslashit( get_stylesheet_directory() ) . $this->settings_save_file, __CLASS__ );

    $this->default_settings = $this->get_default_settings();

  }

  /**
   * Check if settings are stored in a file
   *
   * @return bool
   */
  public function is_file_stored(): bool {

    /**
     * Use this filter to determine if settings should be stored in a file
     *
     * @hook findstr_settings_file_stored
     *
     * @param {bool} $is_file_stored set to true if settings should be stored in a file
     *
     * @return {bool} $is_file_stored
     */
    return apply_filters( 'findstr_settings_file_stored', is_file( $this->settings_save_file ) );
  }

  public function set( $name, $value ): void {

    $new = $this->get_all() ?? $this->default_settings;

    $new->{$name} = $value;

    $this->update( $new );
  }

  /**
   * Get settings
   *
   * @param $settings
   *
   * @return object
   */
  public function update( $settings ): object {

      //clean up settings
      $settings = json_decode( wp_json_encode( $settings ) );

    if ( $this->is_file_stored() ) {
      //save settings in local file
      Helpers::file_put_content( $this->settings_save_file, wp_json_encode( $settings, JSON_PRETTY_PRINT ) );
    }

      //update settings in database, just in case
      update_option( $this->settings_option_name, $settings );

      $this->settings = $settings;

      return $settings;
  }

  public function get( string $option_name = '', $default = null ) {
    $settings = $this->get_all() ?? $this->default_settings;

    if ( ! empty( $option_name ) ) {
      return $settings->{$option_name} ?? $default;
    }

    return $settings;
  }

  /**
   * Get all settings
   *
   * @return object|null
   */
  public function get_all(): ?object {

    $current_class = get_class( $this );

    //check if settings are cached
    if ( ! empty( self::$findstr_cached_settings[ $current_class ] ) ) {
      if ( gettype( self::$findstr_cached_settings[ $current_class ] ) === 'object' ) {
        return self::$findstr_cached_settings[ $current_class ];
      }
    }

    //check if settings are saved in local file
    if ( is_file( $this->settings_save_file ) ) {
      $settings_json = file_get_contents( $this->settings_save_file, true );
      if ( ! empty( $settings_json ) ) {
        $settings = json_decode( $settings_json, false );
        if ( ! empty( $settings ) && gettype( $settings ) === 'object' ) {
          self::$findstr_cached_settings[ $current_class ] = $settings;
          return $settings;
        }
      }
    }

    //check if settings are saved in database
    $settings = get_option( $this->settings_option_name );
    if ( ! empty( $settings ) && gettype( $settings ) === 'object' ) {
      self::$findstr_cached_settings[ $current_class ] = $settings;

      return $settings;
    }

    return null;
  }


  public function get_default_settings(): object {
    return (object) array(
      'postTypes' => array( 'post', 'page' ),
    );
  }


  public function get_post_types_to_index(): array {

    $settings = new Settings();

    /**
     * Filter the post types to index
     *
     * @hook findstr_indexable_post_types
     *
     * @param {array} $post_types_to_index
     *
     * @return {array} $post_types_to_index
     */
    $this->post_types_to_index = (array) apply_filters(
      'findstr_indexable_post_types',
      $settings->get( 'postTypes' )
    );

    return $this->post_types_to_index;
  }

}