{"id":21611503,"url":"https://github.com/underpin-wp/admin-page-loader","last_synced_at":"2026-05-20T06:06:29.172Z","repository":{"id":57075274,"uuid":"364416374","full_name":"Underpin-WP/admin-page-loader","owner":"Underpin-WP","description":"Underpin loader to render, save, and register settings pages in WordPress","archived":false,"fork":false,"pushed_at":"2021-11-22T12:50:12.000Z","size":22,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-08T01:01:52.217Z","etag":null,"topics":["underpin","wordpress"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Underpin-WP.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-05-04T23:53:56.000Z","updated_at":"2021-08-05T13:18:46.000Z","dependencies_parsed_at":"2022-08-24T14:55:41.917Z","dependency_job_id":null,"html_url":"https://github.com/Underpin-WP/admin-page-loader","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Underpin-WP%2Fadmin-page-loader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Underpin-WP%2Fadmin-page-loader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Underpin-WP%2Fadmin-page-loader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Underpin-WP%2Fadmin-page-loader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Underpin-WP","download_url":"https://codeload.github.com/Underpin-WP/admin-page-loader/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244257304,"owners_count":20424131,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["underpin","wordpress"],"created_at":"2024-11-24T21:12:55.738Z","updated_at":"2026-05-20T06:06:29.148Z","avatar_url":"https://github.com/Underpin-WP.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Underpin Admin Page Loader\n\nLoader That assists with adding admin pages to a WordPress website.\n\n## Installation\n\n### Using Composer\n\n`composer require underpin/admin-page-loader`\n\n### Manually\n\nThis plugin uses a built-in autoloader, so as long as it is required _before_\nUnderpin, it should work as-expected.\n\n`require_once(__DIR__ . '/underpin-admin-pages/admin-pages.php');`\n\n## Setup\n\n1. Install Underpin. See [Underpin Docs](https://www.github.com/underpin-wp/underpin)\n1. Register new admin Pages as-needed.\n\n## Basic Example\n\nA very basic example could look something like this. This example would display a single text field on a settings page,\nand handle field saving using Underpin's fields API.\n\n```php\n// Register the option to use on the settings page. See Underpin_Options\\Abstracts\\Option\nunderpin()-\u003eoptions()-\u003eadd( 'example_admin_options', [\n\t'key'           =\u003e 'example_option', // required\n\t'default_value' =\u003e [\n\t\t'test_setting' =\u003e 'Hello world',\n\t],\n\t'name'          =\u003e 'Example Admin Page',\n\t'description'   =\u003e 'Settings manged by Example Admin Page',\n] );\n\n// Register the admin page\nunderpin()-\u003eadmin_pages()-\u003eadd( 'example-admin-page', [\n\t'page_title' =\u003e underpin()-\u003e__( 'Example Admin Page' ),\n\t'menu_title' =\u003e underpin()-\u003e__( 'Example' ),\n\t'capability' =\u003e 'administrator',\n\t'menu_slug'  =\u003e 'example-admin-page',\n\t'icon'       =\u003e 'dashicons-admin-site-alt',\n\t'position'   =\u003e 5,\n\t'sections'   =\u003e [\n\t\t[\n\t\t\t'id'          =\u003e 'primary-section',\n\t\t\t'name'        =\u003e underpin()-\u003e__( 'Primary Section' ),\n\t\t\t'options_key' =\u003e 'example_admin_options',\n\t\t\t'fields'      =\u003e [\n\t\t\t\t'test_setting' =\u003e [\n\t\t\t\t\t'class' =\u003e 'Underpin\\Factories\\Settings_Fields\\Text',\n\t\t\t\t\t'args'  =\u003e [ underpin()-\u003eoptions()-\u003epluck( 'example_admin_options', 'test_setting' ), [\n\t\t\t\t\t\t'name'        =\u003e 'test_setting',\n\t\t\t\t\t\t'description' =\u003e underpin()-\u003e__( 'Optional. Specify the person to say hello to. Default \"world\".' ),\n\t\t\t\t\t\t'label'       =\u003e underpin()-\u003e__( 'Name' ),\n\t\t\t\t\t] ],\n\t\t\t\t],\n\t\t\t],\n\t\t],\n\t],\n] );\n\n```\n\n## Multiple Sections\n\nThe admin screen is broken into sections. This makes it possible to quickly change the layout of the page into various\ndisplay types, such as a tabular layout. This example would display all of the sections on a single page.\n\n```php\n\n// Register the option to use on the settings page. See Underpin_Options\\Abstracts\\Option\nunderpin()-\u003eoptions()-\u003eadd( 'example_admin_options', [\n\t'key'           =\u003e 'example_option', // required\n\t'default_value' =\u003e [\n\t\t'test_setting'    =\u003e 'Hello world',\n\t\t'another_setting' =\u003e 'Second tab setting value',\n\t],\n\t'name'          =\u003e 'Example Admin Page',\n\t'description'   =\u003e 'Settings manged by Example Admin Page',\n] );\n\n// Register the admin page\nunderpin()-\u003eadmin_pages()-\u003eadd( 'example-admin-page', [\n\t'page_title' =\u003e underpin()-\u003e__( 'Example Admin Page' ),\n\t'menu_title' =\u003e underpin()-\u003e__( 'Example' ),\n\t'capability' =\u003e 'administrator',\n\t'menu_slug'  =\u003e 'example-admin-page',\n\t'icon'       =\u003e 'dashicons-admin-site-alt',\n\t'position'   =\u003e 5,\n\t'sections'   =\u003e [\n\t\t[\n\t\t\t'id'          =\u003e 'primary-section',\n\t\t\t'name'        =\u003e underpin()-\u003e__( 'Primary Section' ),\n\t\t\t'options_key' =\u003e 'example_admin_options',\n\t\t\t'fields'      =\u003e [\n\t\t\t\t'test_setting' =\u003e [\n\t\t\t\t\t'class' =\u003e 'Underpin\\Factories\\Settings_Fields\\Text',\n\t\t\t\t\t'args'  =\u003e [ underpin()-\u003eoptions()-\u003epluck( 'example_admin_options', 'test_setting' ), [\n\t\t\t\t\t\t'name'        =\u003e 'test_setting',\n\t\t\t\t\t\t'description' =\u003e underpin()-\u003e__( 'This is a description of this setting' ),\n\t\t\t\t\t\t'label'       =\u003e underpin()-\u003e__( 'Setting Name' ),\n\t\t\t\t\t] ],\n\t\t\t\t],\n\t\t\t],\n\t\t],\n\t\t[\n\t\t\t'id'          =\u003e 'secondary-section',\n\t\t\t'name'        =\u003e underpin()-\u003e__( 'Secondary Section' ),\n\t\t\t'options_key' =\u003e 'example_admin_options',\n\t\t\t'fields'      =\u003e [\n\t\t\t\t'test_setting' =\u003e [\n\t\t\t\t\t'class' =\u003e 'Underpin\\Factories\\Settings_Fields\\Text',\n\t\t\t\t\t'args'  =\u003e [ underpin()-\u003eoptions()-\u003epluck( 'example_admin_options', 'another_setting' ), [\n\t\t\t\t\t\t'name'        =\u003e 'another_setting',\n\t\t\t\t\t\t'description' =\u003e underpin()-\u003e__( 'This is a description of this setting' ),\n\t\t\t\t\t\t'label'       =\u003e underpin()-\u003e__( 'Secondary Setting Name' ),\n\t\t\t\t\t] ],\n\t\t\t\t],\n\t\t\t],\n\t\t],\n\t],\n] );\n```\n\n## Sections as Tabs\n\nTo change the display to use tabs, simply set the `type` argument to `tabs`.\n\n```php\n\n// Register the option to use on the settings page. See Underpin_Options\\Abstracts\\Option\nunderpin()-\u003eoptions()-\u003eadd( 'example_admin_options', [\n\t'key'           =\u003e 'example_option', // required\n\t'default_value' =\u003e [\n\t\t'test_setting'    =\u003e 'Hello world',\n\t\t'another_setting' =\u003e 'Second tab setting value',\n\t],\n\t'name'          =\u003e 'Example Admin Page',\n\t'description'   =\u003e 'Settings manged by Example Admin Page',\n] );\n\n// Register the admin page\nunderpin()-\u003eadmin_pages()-\u003eadd( 'example-admin-page', [\n\t'page_title' =\u003e underpin()-\u003e__( 'Example Admin Page' ),\n\t'menu_title' =\u003e underpin()-\u003e__( 'Example' ),\n\t'capability' =\u003e 'administrator',\n\t'menu_slug'  =\u003e 'example-admin-page',\n\t'layout'     =\u003e 'tabs',\n\t'icon'       =\u003e 'dashicons-admin-site-alt',\n\t'position'   =\u003e 5,\n\t'sections'   =\u003e [\n\t\t[\n\t\t\t'id'          =\u003e 'primary-section',\n\t\t\t'name'        =\u003e underpin()-\u003e__( 'Primary Section' ),\n\t\t\t'options_key' =\u003e 'example_admin_options',\n\t\t\t'fields'      =\u003e [\n\t\t\t\t'test_setting' =\u003e [\n\t\t\t\t\t'class' =\u003e 'Underpin\\Factories\\Settings_Fields\\Text',\n\t\t\t\t\t'args'  =\u003e [ underpin()-\u003eoptions()-\u003epluck( 'example_admin_options', 'test_setting' ), [\n\t\t\t\t\t\t'name'        =\u003e 'test_setting',\n\t\t\t\t\t\t'description' =\u003e underpin()-\u003e__( 'This is a description of this setting' ),\n\t\t\t\t\t\t'label'       =\u003e underpin()-\u003e__( 'Setting Name' ),\n\t\t\t\t\t] ],\n\t\t\t\t],\n\t\t\t],\n\t\t],\n\t\t[\n\t\t\t'id'          =\u003e 'secondary-section',\n\t\t\t'name'        =\u003e underpin()-\u003e__( 'Secondary Section' ),\n\t\t\t'options_key' =\u003e 'example_admin_options',\n\t\t\t'fields'      =\u003e [\n\t\t\t\t'test_setting' =\u003e [\n\t\t\t\t\t'class' =\u003e 'Underpin\\Factories\\Settings_Fields\\Text',\n\t\t\t\t\t'args'  =\u003e [ underpin()-\u003eoptions()-\u003epluck( 'example_admin_options', 'another_setting' ), [\n\t\t\t\t\t\t'name'        =\u003e 'another_setting',\n\t\t\t\t\t\t'description' =\u003e underpin()-\u003e__( 'This is a description of this setting' ),\n\t\t\t\t\t\t'label'       =\u003e underpin()-\u003e__( 'Secondary Setting Name' ),\n\t\t\t\t\t] ],\n\t\t\t\t],\n\t\t\t],\n\t\t],\n\t],\n] );\n```\n\n## Customizing Templates\n\nBy default, layouts are intentionally built to match WordPress. The intent is to provide a fast way to build Admin pages,\nsomething that is typically a time-consuming task. There are many ways to extend how this page behaves, however.\n\n### Option 1: Create Custom Settings Fields\n\nAll of the field rendering happens inside `Setting_Field::place`. In-other words, if you create a custom Setting Field,\nit is possible to create a custom template for a field, and customize how that field behaves when it is saved.\n\n### Option 2: Extend Admin_Page to include custom layouts\n\nAnother option is to extend the relevant functions in `Admin_Page` with your own behavior.\nBy doing so, you will be able to create your own template files that can be used instead of the defaults.\n\nIt's not shown here, but you could also extend pretty much everything, including how options are saved, and where things get\nsaved.\n\n```php\nclass Custom_Page extends \\Underpin_Admin_Pages\\Factories\\Admin_Page_Instance{\n  \n  \n\t/**\n\t * Fetches the valid templates and their visibility.\n\t *\n\t * override_visibility can be either \"theme\", \"plugin\", \"public\" or \"private\".\n\t *  theme   - sets the template to only be override-able by a parent, or child theme.\n\t *  plugin  - sets the template to only be override-able by another plugin.\n\t *  public  - sets the template to be override-able anywhere.\n\t *  private - sets the template to be non override-able.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return array of template properties keyed by the template name\n\t */\n\tpublic function get_templates() {\n\t    if( 'custom-layout' === $this-\u003elayout ){\n\t      return [\n\t        'admin' =\u003e [ // This should match your entry file name for this template.\n\t           'override_visibility' =\u003e 'private' // Or whatever.\n            ]\n          ];\n\t    }\n\t    \n\t    // Fallback to default.\n\t    return parent::get_templates();\n\t}\n\n\t/**\n\t * Fetches the template group name.\n\t *\n\t * @since 1.0.0\n\t *\n\t * @return string The template group name\n\t */\n\tprotected function get_template_group() {\n\t    if('custom-layout' === $this-\u003elayout){\n\t      return 'admin'; // Or whatever you want your subdirectory to be.\n\t    }\n\t    \n\t    // Fallback to default\n\t\treturn parent::get_template_group();\n\t}\n\n\n\t/**\n\t * @inheritDoc\n\t */\n\tprotected function get_template_root_path() {\n\t    if('custom-layout' === $this-\u003elayout){\n\t      return 'custom/root/path';\n\t    }\n\t    \n\t    // Fallback to default\n\t\treturn parent::get_template_root_path();\n\t}\n\n}\n```\n\nYou could then use this factory just like you would normally, only now you must specify the class to use instead of the default.\n\n```php\n\n// Register the admin page\nunderpin()-\u003eadmin_pages()-\u003eadd( 'example-admin-page', [\n\t'class' =\u003e 'Custom_Page', // Name of the class to use\n\t'args'  =\u003e [ // Arguments use to set up this instance.\n\t\t'page_title' =\u003e underpin()-\u003e__( 'Example Admin Page' ),\n\t\t'menu_title' =\u003e underpin()-\u003e__( 'Example' ),\n\t\t'capability' =\u003e 'administrator',\n\t\t'menu_slug'  =\u003e 'example-admin-page',\n\t\t'layout'     =\u003e 'tabs',\n\t\t'icon'       =\u003e 'dashicons-admin-site-alt',\n\t\t'position'   =\u003e 5,\n\t\t'sections'   =\u003e [\n\t\t\t[\n\t\t\t\t'id'          =\u003e 'primary-section',\n\t\t\t\t'name'        =\u003e underpin()-\u003e__( 'Primary Section' ),\n\t\t\t\t'options_key' =\u003e 'example_admin_options',\n\t\t\t\t'fields'      =\u003e [\n\t\t\t\t\t'test_setting' =\u003e [\n\t\t\t\t\t\t'class' =\u003e 'Underpin\\Factories\\Settings_Fields\\Text',\n\t\t\t\t\t\t'args'  =\u003e [ underpin()-\u003eoptions()-\u003epluck( 'example_admin_options', 'test_setting' ), [\n\t\t\t\t\t\t\t'name'        =\u003e 'test_setting',\n\t\t\t\t\t\t\t'description' =\u003e underpin()-\u003e__( 'This is a description of this setting' ),\n\t\t\t\t\t\t\t'label'       =\u003e underpin()-\u003e__( 'Setting Name' ),\n\t\t\t\t\t\t] ],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t\t[\n\t\t\t\t'id'          =\u003e 'secondary-section',\n\t\t\t\t'name'        =\u003e underpin()-\u003e__( 'Secondary Section' ),\n\t\t\t\t'options_key' =\u003e 'example_admin_options',\n\t\t\t\t'fields'      =\u003e [\n\t\t\t\t\t'test_setting' =\u003e [\n\t\t\t\t\t\t'class' =\u003e 'Underpin\\Factories\\Settings_Fields\\Text',\n\t\t\t\t\t\t'args'  =\u003e [ underpin()-\u003eoptions()-\u003epluck( 'example_admin_options', 'another_setting' ), [\n\t\t\t\t\t\t\t'name'        =\u003e 'another_setting',\n\t\t\t\t\t\t\t'description' =\u003e underpin()-\u003e__( 'This is a description of this setting' ),\n\t\t\t\t\t\t\t'label'       =\u003e underpin()-\u003e__( 'Secondary Setting Name' ),\n\t\t\t\t\t\t] ],\n\t\t\t\t\t],\n\t\t\t\t],\n\t\t\t],\n\t\t],\n\t],\n] );\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funderpin-wp%2Fadmin-page-loader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funderpin-wp%2Fadmin-page-loader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funderpin-wp%2Fadmin-page-loader/lists"}