Skip to content

Commit

Permalink
Merge branch 'master' into presave_tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
mboynes committed Feb 20, 2016
2 parents c5caf09 + 8c28773 commit fd9a645
Show file tree
Hide file tree
Showing 21 changed files with 333 additions and 50 deletions.
19 changes: 19 additions & 0 deletions .editorconfig
@@ -0,0 +1,19 @@
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org

# WordPress Coding Standards
# http://make.wordpress.org/core/handbook/coding-standards/

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab
indent_size = 4

[*.json,*.yml,*.feature]
indent_style = space
indent_size = 2
4 changes: 4 additions & 0 deletions .gitignore
Expand Up @@ -19,3 +19,7 @@ todo.txt
/report/

.svn

composer.lock
/vendor/
/node_modules
7 changes: 6 additions & 1 deletion .travis.yml
Expand Up @@ -24,6 +24,10 @@ matrix:
- php: 7.0
fast_finish: true

branches:
only:
- master

before_script:
- export WP_TESTS_DIR=/tmp/wordpress/tests/phpunit
- export WP_CORE_DIR=/tmp/wordpress/src/
Expand All @@ -36,8 +40,9 @@ before_script:
- npm install -g npm
- npm install -g grunt-cli
- npm install
- composer install

script:
- phpunit
- grunt qunit:specific --wp=$WP_VERSION

- grunt phpcs
13 changes: 12 additions & 1 deletion Gruntfile.js
Expand Up @@ -34,11 +34,22 @@ module.exports = function( grunt ) {
urls: [ 'http://localhost:8000/tests/js/index.html?wp=' + grunt.option( 'wp' ) ]
}
}
}
},
phpcs: {
plugin: {
src: './'
},
options: {
bin: "vendor/bin/phpcs --extensions=php --ignore=\"*/vendor/*,*/node_modules/*,/*\"",
standard: "phpcs.ruleset.xml"
}
},
});


grunt.loadNpmTasks( 'grunt-contrib-connect' );
grunt.loadNpmTasks( 'grunt-contrib-qunit' );
grunt.loadNpmTasks( 'grunt-phpcs' );

grunt.task.run( 'connect' );

Expand Down
6 changes: 4 additions & 2 deletions README.md
@@ -1,7 +1,9 @@
# Fieldmanager <img align="right" src="https://travis-ci.org/alleyinteractive/wordpress-fieldmanager.png?branch=master" alt="Travis CI Build Status" />
# Fieldmanager

Fieldmanager is a comprehensive toolkit for building forms, metaboxes, and custom admin screens for WordPress.

[![Build Status](https://travis-ci.org/alleyinteractive/wordpress-fieldmanager.svg?branch=master)](https://travis-ci.org/alleyinteractive/wordpress-fieldmanager)

## Using Fieldmanager in your WordPress Project

Fieldmanager is a powerful library which can make the development of sophisticated features a breeze. To get started, simply [download](#downloads-and-versioning) and install this plugin into your plugins directory and activate it on the plugins screen. To learn how to use Fieldmanager's API, visit the project's official website at [Fieldmanager.org](http://fieldmanager.org). There is also [a demo plugin](https://github.com/alleyinteractive/fieldmanager-demos) which illustrates a lot of what you can do with Fieldmanager.
Expand All @@ -26,4 +28,4 @@ apigen -c apigen.neon

## Running QUnit tests

Fieldmanager uses QUnit for JavaScript unit tests. To quickly check the status of the tests, open `/tests/js/index.html` in your browser. You can also run the tests from the command line: Install the dependencies with `npm install`, then use `grunt qunit:latest` to run the tests against WordPress trunk or `grunt qunit:recent` to run the tests against trunk and the last two major releases.
Fieldmanager uses QUnit for JavaScript unit tests. To quickly check the status of the tests, open `/tests/js/index.html` in your browser. You can also run the tests from the command line: Install the dependencies with `npm install`, then use `grunt qunit:latest` to run the tests against WordPress trunk or `grunt qunit:recent` to run the tests against trunk and the last two major releases.
17 changes: 17 additions & 0 deletions composer.json
@@ -0,0 +1,17 @@
{
"name": "alleyinteractive/wordpress-fieldmanager",
"authors": [
{
"name": "Alley Interactive",
"email": "noreply@alleyinteractive.com"
}
],
"require-dev": {
"squizlabs/php_codesniffer": "2.3.4",
"wp-coding-standards/wpcs": "0.8.0"
},
"scripts": {
"post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths vendor/wp-coding-standards/wpcs",
"post-update-cmd" : "\"vendor/bin/phpcs\" --config-set installed_paths vendor/wp-coding-standards/wpcs"
}
}
1 change: 0 additions & 1 deletion css/fieldmanager.css
Expand Up @@ -328,7 +328,6 @@ div.fm-group-label-wrapper .fmjs-remove {
background: #fff;
height: 100px;
width: 600px;
border: solid 1px #444;
padding: 5px;
margin: 10px 0;
}
Expand Down
5 changes: 3 additions & 2 deletions fieldmanager.php
Expand Up @@ -101,7 +101,7 @@ function fieldmanager_load_file( $file ) {
*/
function fieldmanager_enqueue_scripts() {
wp_enqueue_script( 'fieldmanager_script', fieldmanager_get_baseurl() . 'js/fieldmanager.js', array( 'jquery' ), '1.0.7' );
wp_enqueue_style( 'fieldmanager_style', fieldmanager_get_baseurl() . 'css/fieldmanager.css', array(), '1.0.3' );
wp_enqueue_style( 'fieldmanager_style', fieldmanager_get_baseurl() . 'css/fieldmanager.css', array(), '1.0.4' );
wp_enqueue_script( 'jquery-ui-sortable' );
}
add_action( 'admin_enqueue_scripts', 'fieldmanager_enqueue_scripts' );
Expand Down Expand Up @@ -355,6 +355,7 @@ function fm_calculate_context() {
break;
// Context = "term".
case 'edit-tags.php':
case 'term.php': // As of 4.5-alpha; see https://core.trac.wordpress.org/changeset/36308
if ( !empty( $_POST['taxonomy'] ) ) {
$calculated_context = array( 'term', sanitize_text_field( $_POST['taxonomy'] ) );
} elseif ( !empty( $_GET['taxonomy'] ) ) {
Expand Down Expand Up @@ -578,4 +579,4 @@ class FM_Developer_Exception extends Exception { }
*
* @package Fieldmanager
*/
class FM_Validation_Exception extends Exception { }
class FM_Validation_Exception extends Exception { }
5 changes: 3 additions & 2 deletions package.json
Expand Up @@ -10,6 +10,7 @@
"devDependencies": {
"grunt": "^0.4.5",
"grunt-contrib-connect": "~0.11.0",
"grunt-contrib-qunit": "~0.7.0"
"grunt-contrib-qunit": "~0.7.0",
"grunt-phpcs": "^0.4.0"
}
}
}
6 changes: 4 additions & 2 deletions php/class-fieldmanager-autocomplete.php
Expand Up @@ -146,8 +146,10 @@ public function form_element( $value = Null ) {
* @param array $current_values existing post values
*/
public function presave_alter_values( $values, $current_values = array() ) {
// return if there are no saved values, if this isn't a post, or if the reciprocal relationship isn't set.
if ( empty( $this->data_id ) || $this->data_type !== 'post' ) return $values;
// return if there is no data id
if ( empty( $this->data_id ) ) {
return $values;
}
return $this->datasource->presave_alter_values( $this, $values, $current_values );
}

Expand Down
43 changes: 26 additions & 17 deletions php/class-fieldmanager-field.php
Expand Up @@ -94,6 +94,12 @@ abstract class Fieldmanager_Field {
*/
public $description = '';

/**
* @var boolean
* If true, the description will be displayed after the element.
*/
public $description_after_element = true;

/**
* @var string|boolean[]
* Extra HTML attributes to apply to the form element. Use boolean true to apply a standalone attribute, e.g. 'required' => true
Expand Down Expand Up @@ -341,25 +347,24 @@ public function __construct( $label = '', $options = array() ) {
* @throws FM_Developer_Exception if an option is set but not public.
*/
public function set_options( $label, $options ) {
if ( is_array( $label ) ) $options = $label;
else $options['label'] = $label;

foreach ( $options as $k => $v ) {
try {
$reflection = new ReflectionProperty( $this, $k ); // Would throw a ReflectionException if item doesn't exist (developer error)
if ( $reflection->isPublic() ) $this->$k = $v;
else throw new FM_Developer_Exception; // If the property isn't public, don't set it (rare)
} catch ( Exception $e ) {
if ( is_array( $label ) ) {
$options = $label;
} else {
$options['label'] = $label;
}

// Get all the public properties for this object
$properties = call_user_func( 'get_object_vars', $this );

foreach ( $options as $key => $value ) {
if ( array_key_exists( $key, $properties ) ) {
$this->$key = $value;
} elseif ( self::$debug ) {
$message = sprintf(
__( 'You attempted to set a property "%1$s" that is nonexistant or invalid for an instance of "%2$s" named "%3$s".', 'fieldmanager' ),
$k, __CLASS__, !empty( $options['name'] ) ? $options['name'] : 'NULL'
$key, get_class( $this ), !empty( $options['name'] ) ? $options['name'] : 'NULL'
);
$title = esc_html__( 'Nonexistant or invalid option', 'fieldmanager' );
if ( !self::$debug ) {
wp_die( esc_html( $message ), $title );
} else {
throw new FM_Developer_Exception( esc_html( $message ) );
}
throw new FM_Developer_Exception( esc_html( $message ) );
}
}

Expand Down Expand Up @@ -534,6 +539,10 @@ public function single_element_markup( $value = Null, $is_proto = False ) {
}
}

if ( isset( $this->description ) && !empty( $this->description ) && ! $this->description_after_element ) {
$out .= sprintf( '<div class="fm-item-description">%s</div>', $this->escape( 'description' ) );
}

if ( Null === $value && Null !== $this->default_value )
$value = $this->default_value;

Expand All @@ -547,7 +556,7 @@ public function single_element_markup( $value = Null, $is_proto = False ) {

if ( $render_label_after ) $out .= $label;

if ( isset( $this->description ) && !empty( $this->description ) ) {
if ( isset( $this->description ) && !empty( $this->description ) && $this->description_after_element ) {
$out .= sprintf( '<div class="fm-item-description">%s</div>', $this->escape( 'description' ) );
}

Expand Down
16 changes: 11 additions & 5 deletions php/class-fieldmanager-group.php
Expand Up @@ -307,15 +307,21 @@ public function presave( $values, $current_values = array() ) {
foreach ( $this->children as $k => $element ) {
$element->data_id = $this->data_id;
$element->data_type = $this->data_type;
if ( empty( $values[$element->name] ) ) {
if ( ! isset( $values[ $element->name ] ) ) {
$values[ $element->name ] = NULL;
}

if ( $element->skip_save ) {
unset( $values[ $element->name ] );
continue;
}

$child_value = empty( $values[ $element->name ] ) ? Null : $values[ $element->name ];
$current_child_value = !isset( $current_values[$element->name ]) ? array() : $current_values[$element->name];
$current_child_value = ! isset( $current_values[ $element->name ] ) ? array() : $current_values[ $element->name ];
$values[ $element->name ] = $element->presave_all( $values[ $element->name ], $current_child_value );
if ( !$this->save_empty && $this->limit != 1 ) {
if ( is_array( $values[$element->name] ) && empty( $values[$element->name] ) ) unset( $values[$element->name] );
elseif ( empty( $values[$element->name] ) ) unset( $values[$element->name] );
if ( ! $this->save_empty && $this->limit != 1 ) {
if ( is_array( $values[ $element->name ] ) && empty( $values[ $element->name ] ) ) unset( $values[ $element->name ] );
elseif ( empty( $values[ $element->name ] ) ) unset( $values[ $element->name ] );
}
}

Expand Down
4 changes: 1 addition & 3 deletions php/class-fieldmanager-options.php
Expand Up @@ -55,6 +55,7 @@ abstract class Fieldmanager_Options extends Fieldmanager_Field {
* @param mixed $options
*/
public function __construct( $label = '', $options = array() ) {
$this->sanitize = array( $this, 'sanitize' );
parent::__construct( $label, $options );

if ( !empty( $this->options ) ) {
Expand All @@ -63,9 +64,6 @@ public function __construct( $label = '', $options = array() ) {

// Add the options CSS
fm_add_style( 'fm_options_css', 'css/fieldmanager-options.css' );

// Sanitization
$this->sanitize = array( $this, 'sanitize' );
}

/**
Expand Down
15 changes: 14 additions & 1 deletion php/context/class-fieldmanager-context-storable.php
Expand Up @@ -9,6 +9,11 @@
*/
abstract class Fieldmanager_Context_Storable extends Fieldmanager_Context {

/**
* @var array
*/
public $taxonomies_to_save = array();

/**
* Render the field.
*
Expand Down Expand Up @@ -39,6 +44,7 @@ protected function save( $data = null ) {
// Reset the save keys in the event this context instance is saved twice
$this->save_keys = array();

$this->fm->current_context = $this;
if ( $this->fm->serialize_data ) {
$this->save_field( $this->fm, $data, $this->fm->data_id );
} else {
Expand All @@ -47,6 +53,12 @@ protected function save( $data = null ) {
}
$this->save_walk_children( $this->fm, $data, $this->fm->data_id );
}
if ( ! empty( $this->taxonomies_to_save ) ) {
foreach( $this->taxonomies_to_save as $taxonomy => $data ) {
wp_set_object_terms( $this->fm->data_id, $data['term_ids'], $taxonomy, $data['append'] );
}
$this->taxonomies_to_save = array();
}
}

/**
Expand Down Expand Up @@ -205,4 +217,5 @@ abstract protected function update_data( $data_id, $data_key, $data_value, $data
* @see delete_post_meta().
*/
abstract protected function delete_data( $data_id, $data_key, $data_value = '' );
}

}
29 changes: 20 additions & 9 deletions php/datasource/class-fieldmanager-datasource-term.php
Expand Up @@ -192,11 +192,11 @@ public function presave_alter_values( Fieldmanager_Field $field, $values, $curre
$tax_values = $value;
}
}
$this->save_taxonomy( $tax_values, $field->data_id );
$this->pre_save_taxonomy( $tax_values, $field );
}
if ( $this->only_save_to_taxonomy ) {
if ( empty( $values ) && ! ( $this->append_taxonomy ) ) {
$this->save_taxonomy( array(), $field->data_id );
$this->pre_save_taxonomy( array(), $field );
}
return array();
}
Expand All @@ -215,26 +215,37 @@ public function presave( Fieldmanager_Field $field, $value, $current_value ) {
* @param mixed[] $tax_values
* @return void
*/
public function save_taxonomy( $tax_values, $data_id ) {
public function pre_save_taxonomy( $tax_values, $field ) {

$tax_values = array_map( 'intval', $tax_values );
$tax_values = array_unique( $tax_values );
$taxonomies = $this->get_taxonomies();

$tree = $field->get_form_tree();
$oldest_parent = array_shift( $tree );

foreach( $taxonomies as $taxonomy ) {
if ( ! isset( $oldest_parent->current_context->taxonomies_to_save[ $taxonomy ] ) ) {
$oldest_parent->current_context->taxonomies_to_save[ $taxonomy ] = array(
'term_ids' => array(),
'append' => $this->append_taxonomy,
);
} else {
// Append any means append all
$oldest_parent->current_context->taxonomies_to_save[ $taxonomy ]['append'] = $oldest_parent->current_context->taxonomies_to_save[ $taxonomy ]['append'] && $this->append_taxonomy;
}
}

// Store the each term for this post. Handle grouped fields differently since multiple taxonomies are present.
if ( count( $taxonomies ) > 1 ) {
// Build the taxonomy insert data
$taxonomies_to_save = array();
foreach ( $tax_values as $term_id ) {
$term = $this->get_term( $term_id );
if ( empty( $taxonomies_to_save[ $term->taxonomy ] ) ) $taxonomies_to_save[ $term->taxonomy ] = array();
$taxonomies_to_save[ $term->taxonomy ][] = $term_id;
}
foreach ( $taxonomies_to_save as $taxonomy => $terms ) {
wp_set_object_terms( $data_id, $terms, $taxonomy, $this->append_taxonomy );
$oldest_parent->current_context->taxonomies_to_save[ $term->taxonomy ]['term_ids'][] = $term_id;
}
} else {
wp_set_object_terms( $data_id, $tax_values, $taxonomies[0], $this->append_taxonomy );
$oldest_parent->current_context->taxonomies_to_save[ $taxonomies[0] ]['term_ids'] = array_merge( $oldest_parent->current_context->taxonomies_to_save[ $taxonomies[0] ]['term_ids'], $tax_values );
}
}

Expand Down
2 changes: 1 addition & 1 deletion php/datasource/class-fieldmanager-datasource-user.php
Expand Up @@ -141,7 +141,7 @@ public function get_items( $fragment = Null ) {
$ret = array();

if ( $fragment ) {
$user_args['search'] = $fragment;
$user_args['search'] = '*' . $fragment . '*';
}

$users = get_users( $user_args );
Expand Down

0 comments on commit fd9a645

Please sign in to comment.