Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inheritable Cascading Settings #597

Open
actual-saurabh opened this issue Jun 27, 2018 · 4 comments
Open

Inheritable Cascading Settings #597

actual-saurabh opened this issue Jun 27, 2018 · 4 comments
Labels
Type: Enhancement Improvements existing features or code
Milestone

Comments

@actual-saurabh
Copy link
Contributor

An issue to keep track of this future feature and take notes

@actual-saurabh actual-saurabh added Type: Enhancement Improvements existing features or code language-php labels Jun 27, 2018
@actual-saurabh actual-saurabh added this to the Future milestone Jun 27, 2018
@actual-saurabh
Copy link
Contributor Author

actual-saurabh commented Jun 27, 2018

Based on a general idea that options can be set up at the global level ($lifterlms), at the level of a specific module and so on, each of the objects can share an options trait to manage all options at the level of the object under a single key.

Each such object will have an id, including the whole plugin itself where $id = 'lifterlms':

<?php

defined( 'ABSPATH' ) || exit;

namespace LLMS\Core;

trait Options {

	private $options = array();
	private $default_options = array();
	public $name = '';

	public function init_options() {
		if ( empty( $this->name ) && ! empty( $this->id ) ) {
			$this->name = \LLMS\PREFIX . $this->id;
		}
		$this->options = get_option( $this->name, $this->default_options );
	}

	public function get_option( $key ) {

		if ( empty( $this->options ) ) {
			$this->init_options();
		}

		if ( array_key_exists( $key, $this->options ) ) {
			return $this->options[ $key ];
		}

		return false;
	}

	public function set_option( $key, $value ) {

		if ( empty( $this->options ) ) {
			$this->init_options();
		}

		if ( array_key_exists( $key, $this->options ) ) {
			$this->options[ $key ] = $value;
		}

		return $this->refresh_options();
	}

	public function refresh_options() {

		return update_option( $this->name, $this->options );
	}

}

@actual-saurabh
Copy link
Contributor Author

actual-saurabh commented Jun 27, 2018

At the level of elements (#522), if each course element is thought to be made up of the actual course element (a post type or custom object) and the associated content object (a post type), they can share the settings trait that handles the trickling:

<?php

defined( 'ABSPATH' ) || exit;

namespace LLMS\Core;

use LLMS\Core as Core;

trait Settings {

	use Core\Options;

        use Core\Meta;

	public function get_setting( $key, $computed = false ) {

		if ( ! is_a( $this, "\WP_Post" ) ) {
			return $this->get_option( $key );
		}

		$setting = get_post_meta( $this->ID, \LLMS\PREFIX . 'setting-' . $key, true );

		if ( $setting === 'inherit' && $computed === true ) {
			$inherited_setting = get_post_meta( $this->ID, \LLMS\PREFIX . 'setting-' . $key . '-inherited', true );

			return $inherited_setting;
		}

		return $setting;
	}

	public function get_computed_setting( $key ) {

		$setting = $this->get_setting( $key, true );

		return $setting;
	}

	public function set_setting( $key, $value ) {

		if ( ! is_a( $this, "\WP_Post" ) ) {
			return $this->set_option( $key );
		}

		$inherited_set = true;

		if ( 'inherit' === $value ) {

			$inherited_value = $this->get_inherited_setting( $key );
			$inherited_set = update_post_meta( $this->ID, \LLMS\PREFIX . 'setting-' . $key . '-inherited', $inherited_value );
		}

		if ( ! $inherited_set ) {
			return $inherited_set;
		}

		return update_post_meta( $this->ID, \LLMS\PREFIX . 'setting-' . $key, $value );
	}

	public function delete_setting( $key ) {

		if ( ! is_a( $this, "\WP_Post" ) ) {
			return $this->delete_option( $key );
		}

		$inherited_deleted = delete_post_meta( $this->ID, \LLMS\PREFIX . 'setting-' . $key . '-inherited' );

		if ( ! $inherited_deleted ) {
			return $inherited_deleted;
		}

		return delete_post_meta( $this->ID, \LLMS\PREFIX . 'setting-' . $key );
	}

	public function get_inherited_setting( $key ) {

		//traverse upwards through tree till the setting is not inherit

		/*
		 * Or maybe, a better idea would be to just look one level above.
		 * If the level above is also 'inherit', get the computed value.
		 * However, this heavily depends on the assumption that
		 * the computed setting is correct on the immediately higher level
		 */

		// if the root also has inherit, look for global options
		global $llms;

		return $llms->get_option( $key );
	}

}

A fallback to options for objects that don't support metadata is built in so that the same interface (get_setting(), set_setting() etc) can be used across the whole system.

@actual-saurabh
Copy link
Contributor Author

actual-saurabh commented Jun 27, 2018

Finally, for any other content object specific metadata, there can be a meta trait where the course element has a property called $object which basically is just a WP_Post object so that any post type can be placed on the course:

<?php

defined( 'ABSPATH' ) || exit;

namespace LLMS\Core;

use LLMS\Core as Core;

trait Meta{

	public function get_object_meta( $key ){

		if( !property_exists( $this, 'object' ) ){
			return false;
		}

		return get_post_meta( $this->object->ID, \LLMS\PREFIX . $key , true );

	}

	public function set_object_meta( $key, $value ){

		if( !property_exists( $this, 'object' ) ){
			return false;
		}

		return update_post_meta( $this->object->ID, \LLMS\PREFIX . $key , $value );

	}

	public function delete_object_meta( $key ){

		if( !property_exists( $this, 'object' ) ){
			return false;
		}

		return delete_post_meta( $this->object->ID, \LLMS\PREFIX . $key );

	}
}

@actual-saurabh
Copy link
Contributor Author

Related #521

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type: Enhancement Improvements existing features or code
Projects
None yet
Development

No branches or pull requests

2 participants