WordPress.org

Plugin Directory

Test out the new Plugin Directory and let us know what you think.

Admin Page Framework

Facilitates WordPress plugin and theme development.

About the Project

What is this for?

This is a PHP class-based WordPress library that helps to create option pages and form fields in the administration area. In addition, it helps to manage to save, export, and import options.

Who needs it?

WordPress plugin/theme developers who publish own products and want to speed up creating setting forms, widgets, contact form etc. and don't want to require their users to install extra dependencies.

Do my plugin/theme users have to install Admin Page Framework?

No. Include the generated framework files in your distribution package. You can generate your own framework files via Dashboard -> Admin Page Framework -> Tools -> Generator.

Where can I get the framework files to include?

Go to Dashboard -> Admin Page Framework -> Tools -> Generator and download the files.

Does my commercial product incorporating your framework library have to be released under GPL2v+?

No. The loader plugin is released under GPLv2 or later but the library itself is released under MIT. Make sure to include only the library file.

Does the framework work with WordPress Multi-site?

Yes, it works with WordPress MU.

Technical Questions

Can I set a custom post type as a root page?

Yes. For built-in root menu items or to create your own ones, you need to use the setRootMenuPage() method. For root pages of custom post types, use setRootMenuPageBySlug().

$this->setRootMenuPageBySlug( 'edit.php?post_type=apf_posts' );
How do I retrieve the stored options?

The framework stores them as an organized multidimensional array in the options table in a single row. So use the get_option() function and pass the instantiated class name as the key or the custom key if you specify one in the constructor.

For instance, if your instantiated class name is APF then the code would be

$my_options = get_option( 'APF' );

If you are new to PHP, you may feel unconfortable dealing with multi-dimensional arrays because you would call isset() so many times. The framework has a utility method to help retrieve values of multi-dimensional arrays.

$_oUtil = new AdminPageFramework_WPUtility;

$value = $_oUtil->getElement( 
    $my_options,    // (required) subject array 
    array( 'key_in_the_first_depth', 'key_in_the_second_depth' ),   // (required) dimensional path
    'My Default Value Here' // (optional) set your default value in case a value is not set
);

In the framework factory class, you can access the utility object as it is defined already.

$value = $this->oUtil->getElement( $subject, $keys, $default );
Is it possible to use a custom options data for the form instead of the ones used by the framework?

Yes, there are two main means to achieve that.

  1. Use the value argument in the field definition array to suppress the displaying value in the field. See an example. https://gist.github.com/michaeluno/fb4088b922b71710c7fb

  2. Override the options array set to the entire form using the options_{instantiated class name} filter hook or pre-defined method. See an example. https://gist.github.com/michaeluno/fcfac27825aa8a35b90f

When you go with the second method, make sure to pass an empty string, '', to the first parameter of the constructor so that it disables the ability to store submitted form data into the options table.

new MyAdminPage( '' );
How can I add sub-menu pages to the top-level page created by the framework from a separate script?

Say, in your main plugin, your class MyAdminPageClassA created a top-level page. In your extension plugin, you want to add sub-menu pages from another instance MyAdminPageClassB.

In the setUp() method of MyAdminPageClasB, pass the instantiated class name of the main plugin that created the root menu, MyAdminPageClassA, to the setRootMenuPageBySlug() method.

$this->setRootMenuPageBySlug( 'MyAdminPageClassA' );

Another option is to use the set_up_{class name} action hook. The callback method receives the admin page class object and you can access the framework methods to add sub-menu pages.

class ThirdPartyScript {

    public function __construct() { 
        add_action( 'set_up_' . 'MyAdminPageClassA', array( $this, 'replyToAddSubMenuPages' ) );
    }
    
    public function replyToAddSubMenuPages( $oAdminPage ) {
            
        $oAdminPage->addSubMenuPage(
            array(
                'page_slug' => 'my_admin_page_b',
                'title'     => __( 'Example', 'your-text-domain' ),
                'order'     => 20,
            )        
        );
            
    }
        
}
new ThirdPartyScript;

See an example.

I want my users to install the loader plugin but do not want to display any visuals of the loader plugin. Is there a way to disable it?

Enable the silent mode of the loader plugin by setting the APFL_SILENT_MODE constant in your script.

define( 'APFL_SILENT_MODE', true );
Can I create pages in the network admin area?

Yes, See the demo.

Some of my users claim they cannot save options. What would be a possible cause?
  • max_input_vars of PHP settings. If this value is small and the there are lots of form input elements, the user may not be able to save the options.

To increase the value, edit php.ini and add the following line where 10000 is the increased number.

max_input_vars = 10000
  • max_allowed_packet of MySQL settings. Try increasing this value in the my.ini or my.cnf file.

The 500M in the following line is where the increased value should be set.

max_allowed_packet=500M

Please keep in mind that these are just a few of many possibilities. If you encounter a situation that prevented the user from saving options, please report.

My class is getting too big by defining predefined callback methods. Is there a way to separate those?

Yes. The predefine method names also serve as a WordPress filter/action hook name. So you can just add callbacks to those hooks from a separate file.

For example, if you want to move your method content_my_page_slug(), then you would do something like,

function getMyPageContent( $sContent ) {
    return $sContent . ' additional contents here.';
}
add_filter( 'content_my_page_slug', 'getMyPageContent' );

IF you want to move your method load_my_page_slug(), then you would do something like,

function loadMyPage( $oFactory ) {
    // do something when the page loads.
}
add_action( 'load_my_page_slug', 'loadMyPage' );
Custom field types do not seem to show up. What did I do wrong?

Most likely, you have not registered the field type. The check-box in Generator will include the field type files in the zip archive and their paths in the list for the auto-loader loaded by the framework bootstrap file.

This essentially eliminates the use of include() or require(), meaning you can call the custom field type files without using include(). However, the field type is not registered by itself yet.

In order to use a custom field type, you need to instantiate the field type class by passing the extended framework class name. For example, if your framework class name is MyPlugin_AdminPageFramework and the field type class name is Select2CustomFieldType, then you need to do

new Select2CustomFieldType( 'MyPlugin_AdminPageFramework' );

Do this in the load() method in your extended framework class.

public function load() {
    new Select2CustomFieldType( 'MyPlugin_AdminPageFramework' );
}

This enables the select2 custom field type for the class MyPlugin_AdminPageFramework, not for the other classes. So essentially, do this for every class that uses the field type.

I cannot find what I'd like to do in tutorials and documentation. Where else should I look for more information?
  • You may directly read the code of the demo plugin. The demo plugin code is located in the example directory.
  • Ask questions in the support forum.

Getting Involved

I've written a useful class, functions, and even custom field types that will be useful for others! Do you want to include it?

The GitHub repository is available. Raise an issue first and we'll see if changes can be made.

How can I contribute to this project?

There are various ways to do so. Please refer to the contribution guideline.

How can I contribute to improving the documentation?

You are welcome to submit documentation. Please follow the Documentation Guideline.

In addition, your tutorials and snippets for the framework can be listed in the manual. Let us know it here.

More FAQ Items

Check out the questions tagged as FAQ on GitHub.

Tutorials

Index

Roadmap

Check out the milestones and issues on GitHub labeled enhancement.

Requires: 3.4 or higher
Compatible up to: 4.6.1
Last Updated: 2 weeks ago
Active Installs: 600+

Ratings

5 out of 5 stars

Support

0 of 1 support threads in the last two months have been marked resolved.

Got something to say? Need help?

Compatibility

+
=
Not enough data

0 people say it works.
0 people say it's broken.

100,1,1 100,1,1 100,1,1 100,1,1 100,1,1
100,1,1
100,2,2 100,1,1 100,1,1
100,1,1 100,1,1 100,1,1
100,1,1
100,1,1
100,1,1 100,1,1 100,1,1 100,1,1
100,1,1 100,1,1
100,3,3 100,1,1 100,1,1
100,1,1
100,1,1 100,1,1 100,1,1
100,1,1 100,1,1
100,1,1 100,1,1 100,1,1 100,1,1 100,1,1 100,1,1 100,1,1 100,1,1
100,1,1 100,1,1 100,1,1 100,1,1 100,1,1
100,2,2 100,1,1 100,1,1 100,1,1 100,1,1
100,1,1 100,1,1 100,1,1
100,1,1 100,1,1 100,1,1 100,1,1
100,1,1
100,1,1
100,1,1
100,1,1 100,1,1 100,1,1 100,1,1
100,1,1 100,1,1
100,1,1