ThemeFuse / Unyson

A WordPress framework that facilitates the development of WP themes
http://unyson.io
923 stars 218 forks source link

How can I add unyson option to widgets and retrieve their values? #568

Closed danyj closed 7 years ago

danyj commented 9 years ago

Could you please show me best possible way to add any unsyon option to widgets? I would like to add list of custom class names that user can pick to display different widgets style/ It is a simple select with list of class names.

This is what I have in mind but with unyson options http://prntscr.com/76c7vg

llemurya commented 9 years ago

@danyj at the widget_form_callback hook you can run fw()->backend->render_options($options, $values) and at the widget_update_callback you must save your data to the database. Hope this helps.

danyj commented 9 years ago

thnx for the reply but is there any way that you can show it with code sample with one option so I can built on it.

danyj commented 9 years ago

I am having trouble with default value and getting it back

danyj commented 9 years ago

this is what I have

add_action('in_widget_form', 'thz_widget_fields');
add_action('widget_update_callback', 'thz_widget_fields_update_callback');
function thz_widget_fields($instance){

    $settings = $instance->get_settings();

    fw_print($settings);

    $options_array = array();

        $options_array[] = array(

            'widget_style' => array(
                'type'  => 'select',
                'label' => __('Select style','fw'),
                'value' => $settings['widget_style'],
                 'choices' => array(
                     'blue' => __('Blue', 'fw'),
                     'red' => __('Red', 'fw'),
                     'green' => __('Green', 'fw'),

                 ),
            ),
        );  

    echo fw()->backend->render_options($options_array, $data['widget_style'], array(
        'id_prefix' => $option["attr"]["id"] . '-',
        'name_prefix' => $option["attr"]["name"]
    ));

}

function thz_widget_fields_update_callback($instance, $new_instance) {
    $instance['widget_style'] = $new_instance['widget_style'];
    return $instance;
}

but it returns null , I think I missed the field names

http://prntscr.com/76hqyx

llemurya commented 9 years ago

@danyj I am working on make a demo for you please wait. I'll become with an answer.

llemurya commented 9 years ago

@danj I make an extension called danj I created 2 files : class-fw-extension-danj.php with the next content

<?php if ( ! defined( 'FW' ) ) {
    die( 'Forbidden' );
}

class FW_Extension_Danj extends FW_Extension {

    /**
     * Called after all extensions instances was created
     * @internal
     */
    protected function _init() {
        // TODO: Implement _init() method.
        add_action( 'widget_form_callback', array( $this, 'form_callback' ) );
        add_filter( 'widget_update_callback', array( $this, 'update_callback' ) );
    }

    public function form_callback( $instance ) {
        $options = array(
            'danj' => array(
                'type'  => 'text',
                'value' => 'default value'
            )
        );

        $values = array( 'danj' => isset( $instance['danj'] ) ? $instance['danj'] : $options['danj']['value'] );

        echo fw()->backend->render_options( $options, $values );
    }

    public function update_callback( $instance ) {
        $instance['danj'] = FW_Request::POST( 'fw_options/danj' );

        return $instance;
    }
}

and manifest.php with the next content

<?php if ( ! defined( 'FW' ) ) {
    die( 'Forbidden' );
}

$manifest = array();

$manifest['name']        = __( 'Danj', 'fw' );
$manifest['description'] = __( 'Danj demo.', 'fw' );
$manifest['version'] = '1.0.0';
$manifest['display'] = true;
$manifest['standalone'] = true;

Here is the video demo how it works. Please try. If it helps, please close the issue.

danyj commented 9 years ago

you over extended yourself and thank you much for it. simple name hint would have been enough but this is much better. than you!

danyj commented 9 years ago

@llemurya should name and id for the options be changed? if I use the extension as you made it I end up with multiple options and all with same name and ID

49 instances http://prntscr.com/76jg33

llemurya commented 9 years ago

Yes if you want you may change it, the code I wrote is a demo and you can change it how you want.

danyj commented 9 years ago

ok , im getting a hang of it. thnx again

danyj commented 9 years ago

@moldcraft @llemurya OK bud , I know you busy that is why I took the task of #542 on my self and it works very well so far . http://prntscr.com/76m08a

my question is this http://wordpress.stackexchange.com/questions/188648/how-to-get-options-of-all-active-widgets/188651#188651

I have that loop and works fine but it just bugs me to loop that much , but now I found this way to get all widgets options

protected function _init() {
    // TODO: Implement _init() method.
    add_action( 'widget_form_callback', array( $this, 'form_callback' ) );
    add_filter( 'widget_update_callback', array( $this, 'update_callback' ) );
    add_filter( 'dynamic_sidebar_params', array($this, 'widget_params'));

}

public function widget_params( $params ) { 
        //fw_print(  $params  );

        $widget_id      = $params[0]['widget_id'];
        $widget_parts   = explode('-',$widget_id);
        $widget_base_id = $widget_parts[0];
        $widget_number  = $widget_parts[1];         
        $options        = get_option('widget_'.$widget_base_id);
        if($options){
            fw_print(  $options[$widget_number]  );
        }

     return $params;
}

and so far I see it works fine http://prntscr.com/76lzdt

but do you think it is a problem to use that filter or the way I extracted the widget options?

danyj commented 9 years ago

I am almost done but there is no way that I can fix those id's and names , each of them must be unique otherwise the widgets dont display titles and their contents get messed up

the form must use in_widget_form

instead

widget_form_callback

but when I do that the widget is not updating

we need to use this somehow

 $instance->get_field_name('option_name');
$instance->get_field_id('option_name');

but I cant get it to work

can you please provide a valid example with options names and ids matching the widget instance

with this select

    $options = array(

        'view_type' => array(
            'type'  => 'select',
            'label' => false,
            'value' => 'hide',
             'choices' => array(
                 'hide' => __('Hide on selected pages', 'fw'),
                 'show' => __('Show on selected pages', 'fw'),
             ),
        ),

    );
danyj commented 9 years ago

please anyone?

danyj commented 9 years ago

unusable to do this as U extension, moved to plugin and everything works out of the box. made simple html options instead unyson options. sad , I wanted to make this unyson extension. http://prntscr.com/76x50a

thnx for the hellp

llemurya commented 9 years ago

@danyj I made a demo for you please wait 20 minutes to make a video cast.

danyj commented 9 years ago

@llemurya , if you are doing it pay attention to double widget in same widget positon ,

for example the only issue from where everything went down is if you use same widget in same position

for example use text widget twice in same position and you are forced to go native html way because of the widget name and ID

danyj commented 9 years ago

and I also tried with instance->number but you cant hook on it since when widget is firts moved to position that does not exist http://prntscr.com/76x992

just giving pointers where I had the problems

this one is what we need done right since we have to use it

    echo fw()->backend->render_options($options, $values, array(
        'id_prefix' => $data['id_prefix'] . $id . '-',  // native widget way
        'name_prefix' => $data['name_prefix'] . '[' . $id . ']', // native widget way
    ));
llemurya commented 9 years ago

@danyj please see this videocast If this is what you want I will share the code.

danyj commented 9 years ago

yes , that is the one , all must be unique per each widget as seen in console

llemurya commented 9 years ago

@danyj my demo only works with simple option types that didn't have javascript, with javascript exists problems.

<?php if ( ! defined( 'FW' ) ) {
    die( 'Forbidden' );
}

class FW_Extension_Danj extends FW_Extension {

    /**
     * Called after all extensions instances was created
     * @internal
     */
    protected function _init() {
        // TODO: Implement _init() method.
        add_action( 'widget_form_callback', array( $this, 'form_callback' ) );
        add_filter( 'widget_update_callback', array( $this, 'update_callback' ) );
    }

    public function form_callback( $instance ) {

        $options = array(
            'demo1' => array(
                'type'  => 'text',
                'value' => 'default value'
            ),
            'demo2' => array(
                'type'=>'select',
                'choices' => array(
                    'tiger' => 'Tiger',
                    'puma' => 'Puma',
                    'lynx' => 'Lynx',
                    'pantera' => 'Pantera'
                )
            )
        );

        $values = isset( $instance['fw_options'] ) ? $instance['fw_options'] : array();

        echo fw()->backend->render_options( $options, $values );

        return $instance;
    }

    public function update_callback( $instance ) {

        fw()->backend->option_type('color-picker')->enqueue_static();

        $instance['fw_options'] = FW_Request::POST( 'fw_options' );

        return $instance;
    }
}
danyj commented 9 years ago

testing

danyj commented 9 years ago

nope , same thing , does not work right, title is not updating, give me your email il send you the extension, and test it with text widget , add title and add text , it wont update it

if I used same script in plugin it works perfect but i had to use native widget stuff

llemurya commented 9 years ago

@danyj In the demo screencast the title is updating, please make an screencast how you test it.

danyj commented 9 years ago

here with your code

http://screencast.com/t/gGQwAOWs

protected function _init() {
    // TODO: Implement _init() method.

    add_action( 'widget_form_callback', array( $this, 'in_widget_form' ) );
    add_filter( 'widget_update_callback', array( $this, 'widget_update_callback' ) );
    add_filter('sidebars_widgets', array($this, 'sidebars_widgets'));

}

public function in_widget_form( $instance  ) {

    $options = array(

        'view_type' => array(
            'type'  => 'select',
            'label' => false,
            'value' => 'hide',
             'choices' => array(
                 'hide' => __('Hide on selected pages', 'fw'),
                 'show' => __('Show on selected pages', 'fw'),
             ),
        ),

        'assigned_pages' => array(
            'type'  => 'select-multiple',
            'label' =>false,
            'value' => array(),
            'population' => 'array',
            'choices' => array(
                    'all' =>  __('All pages', 'fw'),

                    array(
                        'attr'    => array('label' => __('Miscellaneous', 'fw')),
                        'choices' => $this->thz_list_miscellaneous(),
                    ),

                    array(
                        'attr'    => array('label' => __('Post types', 'fw')),
                        'choices' => $this->thz_list_post_types(),
                    ),

                    array(
                        'attr'    => array('label' => __('Taxonomy Categories', 'fw')),
                        'choices' => $this->thz_list_taxonomies(),
                    ),  

                    array(
                        'attr'    => array('label' => __('Archives', 'fw')),
                        'choices' => $this->thz_list_archives(),
                    ),                          

                ),

        )
    );

    $values = isset( $instance['fw_options'] ) ? $instance['fw_options'] : array();

    echo fw()->backend->render_options( $options, $values );

}

public function widget_update_callback( $instance ) {

    $instance['fw_options'] = FW_Request::POST( 'fw_options' );

    return $instance;
}

and this is with my plugin no FW

http://screencast.com/t/To3E39j9M

llemurya commented 9 years ago

@danyj in widget_form function return the $instance

danyj commented 9 years ago

@llemurya what a rookie mistake!

thank you!!!!

danyj commented 9 years ago

well I guess il make both than one for Unyson one for others :)

danyj commented 9 years ago

@llemurya , yes I also noticed some issues with js , but I guess we will have to require the option static files for them if used in there.

llemurya commented 9 years ago

@danyj We think to make option types compatible in widgets area ,when we will do this feature the javascript problems will be resolved, I tried today make javascript works but is a bit complicated, we know why these problems appear and how to solve it.Hope in the next Unyson realease the compatibility will be in production.

danyj commented 9 years ago

thnx for the info , please do advise what to do in case , since I am about to use multi select which requires js . so is it just a matter of equing the option scripts and if so where should that be done ?

ghost commented 8 years ago

Create {theme}/framework-customizations/extensions/test/class-fw-extension-test.php with the following contents:

<?php if (!defined('FW')) die('Forbidden');

class FW_Extension_Test extends FW_Extension {
    protected function _init() {
        add_filter( 'widget_form_callback', array( $this, '_filter_form_callback' ), 10, 2 );
        add_filter( 'widget_update_callback', array( $this, '_filter_update_callback' ), 10, 4 );
    }

    public function _filter_form_callback( $values, WP_Widget $instance ) {
        $options = $this->get_options('test');
        $prefix = $instance->get_field_id('test');

        $this->print_widget_javascript('fw-ext-test-widget-options-'. $prefix);
        echo '<div class="fw-force-xs" id="fw-ext-test-widget-options-'. esc_attr($prefix) .'">';
        echo fw()->backend->render_options($options, $values, array(
            'id_prefix' => $prefix .'-',
            'name_prefix' => $prefix,
        ));
        echo '</div>';

        return $values;
    }

    public function _filter_update_callback( $values, $new_values, $old_values, WP_Widget $instance ) {
        $options = $this->get_options('test');
        $prefix = $instance->get_field_id('test');

        return array_merge(
            $values,
            fw_get_options_values_from_input($options, FW_Request::POST($prefix, array()))
        );
    }

    private function print_widget_javascript($id) {
        ?><script type="text/javascript">
            jQuery(function($) {
                var selector = '#<?php echo esc_js($id) ?>', timeoutId;

                $(selector).on('remove', function(){ // ReInit options on html replace (on widget Save)
                    clearTimeout(timeoutId);
                    timeoutId = setTimeout(function(){ // wait a few milliseconds for html replace to finish
                        fwEvents.trigger('fw:options:init', { $elements: $(selector) });
                    }, 100);
                });
            });
        </script><?php
    }
}

Create {theme}/framework-customizations/extensions/test/manifest.php with the following contents:

<?php if (!defined('FW')) die('Forbidden');

$manifest = array();
$manifest['display'] = true;
$manifest['standalone'] = true;

Create {theme}/framework-customizations/extensions/test/options/test.php with the following contents:

<?php if (!defined('FW')) die('Forbidden');

$options = array(
    'hello' => array('type' => 'text'),
    'world' => array('type' => 'select', 'choices' => array('first' => 'First', 'second' => 'Second')),
);

Activate the extension from Unyson page and test the options in widgets.

Let me know if there are any bugs.

danyj commented 8 years ago

Does not work right , try it on text widget , once you hit save it deletes title and text on the widget and it also messes up my plugin

when I deactivate it the settings come back

ghost commented 8 years ago

I see that test options work well. What is your plugin, where/how I can test it?

danyj commented 8 years ago

@moldcraft il send it to you on skype

danyj commented 8 years ago

@moldcraft ping me when you online

Priler commented 8 years ago

I have this issue https://github.com/ThemeFuse/Unyson/issues/1329

It's just disapearing after saving ...

ghost commented 8 years ago

@Priler Have you tried the new version?

Priler commented 8 years ago

@moldcraft Yep, still no changes, still disapearing after saving.

ghost commented 8 years ago

Can you give me admin/ftp or teamviewer access to your site? If yes, please send the details to moldcraft[at]email.com

Priler commented 8 years ago

@moldcraft, You are true magician!

I just reactivated my theme (durning uploading it to my host and providing you with FTP access) and ... it works. Strange stuff, thought ...

Priler commented 8 years ago

Oh, and ...

@moldcraft, you forgot, that _filter_form_callback must return $values array, or default widget fields will not be displayed.

So, right way will be:

    public function _filter_form_callback( $values, WP_Widget $instance ) {
        $options = $this->get_options('iconization');
        $prefix = $instance->get_field_id('iconization');

        $this->print_widget_javascript('fw-ext-test-widget-options-'. $prefix);
        echo '<div class="fw-force-xs" id="fw-ext-test-widget-options-'. esc_attr($prefix) .'">';
        echo fw()->backend->render_options($options, $values, array(
            'id_prefix' => $prefix .'-',
            'name_prefix' => $prefix,
        ));
        echo '</div>';

        return $values;
    }

Thanks again!

Priler commented 8 years ago

Now we Rock! http://storage4.static.itmages.com/i/16/0308/h_1457438916_5301535_c382aa4a80.jpeg

danyj commented 8 years ago

@Priler nice one bud , @moldcraft the

 return $values;

in _filter_form_callbackfixes my issues

danyj commented 8 years ago

how do we move the options at the bottom of the widget?

Priler commented 8 years ago

@danyj Use filter priority.

danyj commented 8 years ago

@Priler trying , which one is right ? 10,3 ?

Priler commented 8 years ago

@danyj The first one, more details here https://codex.wordpress.org/Function_Reference/add_filter

danyj commented 8 years ago

no , I meant what order is right , I tried below and very high after 10 and it is not moving

Priler commented 8 years ago

@danyj Yep, seems not working. Try in_widget_form action.

danyj commented 8 years ago

@Priler I tried both , is not moving , and if in_widget_formit trows error

filter_form_callback() must be an instance of WP_Widget