{"id":17144169,"url":"https://github.com/harryfinn/wps-core","last_synced_at":"2026-05-01T06:32:35.041Z","repository":{"id":139564535,"uuid":"60684599","full_name":"harryfinn/wps-core","owner":"harryfinn","description":"Repo for the WPS core functions to allow WPS to be included as a submodule or standalone outside of the WPS theme framework","archived":false,"fork":false,"pushed_at":"2018-01-25T09:40:10.000Z","size":35,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-31T22:26:31.384Z","etag":null,"topics":["framework","php","wordpress"],"latest_commit_sha":null,"homepage":null,"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/harryfinn.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-06-08T09:09:29.000Z","updated_at":"2016-12-05T23:59:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"aa795bcd-4c89-48f6-bca4-9d09fafb7003","html_url":"https://github.com/harryfinn/wps-core","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/harryfinn/wps-core","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harryfinn%2Fwps-core","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harryfinn%2Fwps-core/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harryfinn%2Fwps-core/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harryfinn%2Fwps-core/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/harryfinn","download_url":"https://codeload.github.com/harryfinn/wps-core/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harryfinn%2Fwps-core/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32487376,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-30T13:12:12.517Z","status":"online","status_checked_at":"2026-05-01T02:00:05.856Z","response_time":64,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["framework","php","wordpress"],"created_at":"2024-10-14T20:43:15.384Z","updated_at":"2026-05-01T06:32:35.024Z","avatar_url":"https://github.com/harryfinn.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WPS Core - WordPress, Structured\n\n*Note: This project is a __work in progress__ and therefore subject to change!*\n\n## Intro\n\nThe purpose of `WPS` is to offer a structured approach to WordPress theme\ndevelopment by setting up an framework similar to a standard `MVC` in which to\nmanage the theme.\n\nThis repo is the core library code of WPS, allowing you to manage a WordPress \ntheme within an MVC pattern. This repo should be used as a submodule within \na new WordPress project (although it would be possible to integrate with an\nexisting project).\n\n## Installing\n\nYou can install this repo via submodule or you can download a zip and manually\nadd the files, although this would make it harder to update in the future.\n\nFirst, setup a folder within your WordPress in which to add WPS Core to (I'd\nrecommend using a folder inside your theme named `includes`):\n\n```txt\nmkdir includes \u0026\u0026 cd includes\ngit submodule add git@github.com:harryfinn/wps-core.git wps\ngit submodule update --init --recursive\n```\n\nThis project leverages the `CMB2` library by [WebDevStudios](https://github.com/WebDevStudios/CMB2)\nto power additional custom metaboxes (see section below *Adding CMB2 fields* for\nmore information). This is a submodule dependency within WPS Core and will be\nautomatically added and initialised via the commands above.\n\n## Setup\n\nOnce you have completed the install instructions, the following code needs\nincluding in your functions file, either as standalone class or incorporated\nwithin your existing code/framework.\n\n```php\n# Functions file for loading of core files via autoloading methods\n\nrequire_once(get_template_directory() . '/includes/constants.php');\nrequire_once(WPS_INCLUDES_DIR . '/class.wps.php');\n\nclass MyTheme {\n  public static function init() {\n    WPS::init();\n\n    self::include_wp_functions();\n  }\n\n  private static function include_wp_functions() {\n    // Theme functions, support and includes etc\n  }\n}\n\nMyTheme::init();\n```\n\nInside the folder you have included this repo as a submodule (suggested folder\nto use is `includes`), create a separate file `constants.php` and add the\nfollowing code:\n\n```php\n$template_dir = get_template_directory();\n\n// Sets the directory in which the core wps folder and files are found\ndefine('WPS_INCLUDES_DIR', $template_dir . '/includes/wps');\n\n// Sets the directories for each element of the WPS MVC pattern\ndefine('WPS_APP_DIR', $template_dir . '/app');\ndefine('WPS_MODELS_DIR', $template_dir . '/app/models');\ndefine('WPS_VIEWS_DIR', $template_dir . '/app/views');\ndefine('WPS_CONTROLLERS_DIR', $template_dir . '/app/controllers');\ndefine('WPS_HELPERS_DIR', $template_dir . '/app/helpers');\n\n// Defines load priorities for use with actions and filters\ndefine('LOAD_ON_INIT', 1);\n\n// Sets the cmb2 prefix\ndefine('CMB2_PREFIX', '_cmb2_');\n```\n\nThis file is then referenced in your functions file (see the functions file\nexample code above), allow access to these defined constants across your WP\ntheme.\n\n## Structure\n\nWhilst this repo contains just the core library of WPS and is separate from the\ntheme structure, it is important to note that by using the MVC elements (models,\nviews and controllers) it is necessary to ensure that the defined paths in the\nconstants file match a real folder structure in order for WPS Core to work\ncorrectly.\n\nYou can follow the structure used in the main WPS framework repo or create your\nown when working with just WPS Core. However, it is recommended that a similar\nstructure to the one below is used in order to follow a typical MVC pattern:\n\n```txt\n- wp-theme-folder\n  - app\n    - models\n    - views\n    - controllers\n  - includes (this is where you'd install WPS Core)\n  - functions.php\n  - index.php\n```\n\n### Adding Models\n\nThe `models` folder is designed to house 3 different types of files (which can\nbe separated into subfolders per post type to help with organising these files).\n\nThese types are: custom post type registrations (`model.***.php` files), custom\nmeta fields (`cmb2.***.php` files) and finally decorator files (`class.***.php`\nfiles) which allow for the extending of WordPress functions via hooks/actions to\namend functionality for custom post types and/or custom meta fields.\n\nFor example, to add a new custom post type `book` you would create a subfolder\n`models/book` (these should always be named in the singular) and within this\nfolder add:\n\n```php\nclass Book extends WPS\\Model {\n  public function __construct() {\n    parent::__construct(\n      'book',\n      [\n        'labels' =\u003e [\n          'name' =\u003e 'Books',\n          'singular_name' =\u003e 'Book',\n          'add_new_item' =\u003e 'Add a Book',\n          'edit_item' =\u003e 'Edit Book',\n          'not_found' =\u003e 'No Books found',\n          'not_found_in_trash' =\u003e 'No Books found in bin'\n        ],\n        'menu_position' =\u003e '26.980',\n        'menu_icon' =\u003e 'dashicons-groups',\n        'supports' =\u003e [\n          'title',\n          'page-attributes'\n        ]\n      ]\n    );\n  }\n}\n```\n\nSave this file as `model.book.php` and it will automatically be loaded as part\nof the `WPS` framework, generating a new CPT of `book`.\n\nThe `model.****.php` files are for the constructing and decorating of CPT's,\nalong with adding hooks to additional files for further customisation and should\nfollow the standard `class.` prefix.\n\nThe other type of file, `cmb2.****.php` is explained below.\n\n### Adding CMB2 fields\n\nOfficial guides for creating fields along with all the available options and\nfield types can be found [here](https://github.com/WebDevStudios/CMB2/wiki/Basic-Usage#create-a-metabox)\n\nWPS has autoloaders that will automatically add and load files within the\n`models` folder (and subsequent subfolders) which are prefixed by `cmb2.`. The\nfollowing is a basic example:\n\n```php\n$post_fields = new_cmb2_box([\n  'id' =\u003e 'post_fields',\n  'title' =\u003e __('Additional post content fields', 'cmb2'),\n  'object_types' =\u003e ['post'],\n  'context' =\u003e 'normal',\n  'priority' =\u003e 'high',\n  'show_names' =\u003e true\n]);\n\n$post_fields-\u003eadd_field([\n  'name' =\u003e __('Post author name', 'cmb2'),\n  'desc' =\u003e __('Enter the author name for this post', 'cmb2'),\n  'id' =\u003e CMB2_PREFIX . 'post_author_name',\n  'type'=\u003e 'text'\n]);\n```\n\nSave this file as `cmb2.post-fields.php` and it will automatically be loaded as\npart of the `WPS Core`, generating new custom meta fields for the `post` post\ntype.\n\nNote that `CMB2_PREFIX` is a constant defined within your `constants.php` file\nand should be added before each custom metabox field id.\n\n### Adding Views\n\nThe views folder is designed to house components, reusable sections of code\nalong with template specific blocks to help break down the primary WordPress\ntemplate pages.\n\nA view partial can be rendered into a page template by creating an instance of\nthe view class (you should only have one instance per page) and then calling the\nrender method as shown below:\n\n```php\n$homepage_view = new WPS\\View(get_the_ID());\n$homepage_view-\u003erender('homepage/hero-slider');\n```\n\nThe above code will look within the views folder for a subfolder of `homepage`\ncontaining a file named `hero-slider-tpl.php`. You can pass the filename\nsuffix and file extension (`-tpl.php`), however, these are not required by\ndefault.\n\nThe View's class contains a series of methods to help manage simple interactions\nwith CMB2, the custom metabox library used in this library.\n\nTODO: Add reference list of View methods\n\n#### View Helpers\n\nIn order to reduce the 'mess' that is often found in WordPress templates, helper\nmethods can be created and utilised via any instance of the `WPS\\View` class.\n\nHelper methods should only be used for view based functionality, i.e.\ninteracting with items displayed within a template or subsequent partial, such\nas manipulating the text output for an excerpt. They should not be used for\nquery logic or anything else outside the scope of a view.\n\nTo add a new helper class, create a new php file within the `WPS_HELPERS_DIR`\ndirectory, I'd recommend setting the helper constant to `app/helpers`.\n\nBelow is an example helper file which can be used as a guide:\n\n```php\nclass HomepageHeroHelper {\n  public function format_hero_subtitle($text) {\n    return str_replace(' ', '-', $text);\n  }\n}\n```\n\nThis method can then be called by any view or within any partial/component that\nhas been included via the `render` method via\n`$this-\u003ehelper-\u003eformat_hero_subtitle($subtitle)`\n\n### Adding Controllers\n\nThe `controller` folder is where your controller logic lives, separated into a\nseparate class per post type.\n\nA controller class contains the logic and variables passed into a page template.\nThis could be a query object for a collection of items, i.e. a set of posts for\na listing view. Below is an example of a controller that can be used with a\ncustom post type archive listing view:\n\n```php\nclass PortfolioController extends WPS\\Controller {\n  public function index() {\n    $portfolio_items = [78 =\u003e 'test 1', 87 =\u003e 'test 2'];\n\n    include $this-\u003etemplate;\n  }\n}\n```\n\nIn the example above, the post type is automatically set to the current post\ntype detected by WordPress (via `get_query_var` method) which in turn is what\nlinks up the use of the controllers.\n\nHere the post type is `portfolio`, so the `PortfolioController` class is loaded\nand because the template being requested is the `archive` template\n(`archive-portfolio.php`), the `index` method is called. The `$portfolio_items`\nvariable is then exposed to the template and available within the view.\n\nFor single post type templates, use the following format when naming files:\n`single-{$post_type}.php` in conjunction with the `single` controller method.\n\nFor the blog index page, use the following format: `index-post.php` along with\nthe `index` controller method within the `PostController` class.\n\nNote that each controller is extended off of the `WPS\\Controller` class, this\ncan also be setup to extend from an app specific controller i.e.\n`ApplicationController` rather that directly from `WPS`.\n\nIt is also worth nothing that `WPS Controllers` don't usually require a custom\n`__construct` method as this is autoloaded for you. However, if you need to\napend what is passed to `WPS` upon controller setup, the block below shows you\nthe `__construct` method params:\n\n```php\npublic function __construct($post_type = null, $template_fallback) {\n  parent::__construct($post_type, $template_fallback);\n}\n```\n\n### Adding standalone classes/methods\n\nDuring your WordPress theme development, you'll likely come to a point at which\nyou need to separate function (potentially shared) away from a controller or\nmodel and need to house this somewhere.\n\nWPS supports this 'wildcard' structuring by allowing for concept classes to be\nadded to a subfolder within the `/app` directory.\n\nFor example: You have a class which handles the navigation between post type\nitems (i.e. the next post in the collection). This logic is doesn't belong in\nthe controller or model, not only because it has separate concerns but also\nbecause it can be used across multiple post types. Therefore, we can add the\nclass file (`NextPost` for this example) to a new folder within `/app/concepts`.\n\nThe class must then be namespaced inline with the named parent folder, see the\ncode example below:\n\n```php\n\u003c?php\n\nnamespace Concepts;\n\nclass NextPost {\n  // Class methods go here\n}\n```\n\nTo then call this class in your model or controller, you must reference the\nclass via it's namespace: `$next_post = new Concepts\\NextPost()`.\n\nNote: The subfolder can be named whatever is most appropriate for the containing\nclass(es). If you have a set of classes which handle different external\nservices, a folder named `services` would be better suited. You can add as many\nof these folders as required but keep in mind that this should not be used as a\ngeneral 'dumping ground' for anonymous methods/functionality.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharryfinn%2Fwps-core","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fharryfinn%2Fwps-core","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharryfinn%2Fwps-core/lists"}