---
# System prepended metadata

title: JBC Block Theme

---

# JBC Block Theme

Based on [_s theme](https://github.com/Automattic/_s) with Custom ACF Block MVC



## Theme Requirements

* PHP 8.2+
* [ACF Pro](https://www.advancedcustomfields.com/pro/)
* [ACF Extended](https://www.acf-extended.com/) (optional)


## Development Requirements ##

- [Node.js v12](https://nodejs.org/)
- [Composer](https://getcomposer.org/)

### Quick Start

Clone or download this repository, remname, and then you'll need to do a six-step find and replace on the name in all the templates.

1. Search for `'atlas'` (inside single quotations) to capture the text domain and replace with: `'theme-name'`.
2. Search for `atlas_` to capture all the functions names and replace with: `theme_name_`.
3. Search for `Text Domain: atlas-theme` in `style.css` and replace with: `Text Domain: theme-name`.
4. Search for <code>&nbsp;Atlas</code> (with a space before it) to capture DocBlocks and replace with: <code>&nbsp;Theme_Name</code>.
5. Search for `atlas-` to capture prefixed handles and replace with: `theme-name-`.
6. Search for `ATLAS_` (in uppercase) to capture constants and replace with: `THEME_NAME_`.

### Setup

To start using all the tools that come with `atlas`  you need to install the necessary Node.js and Composer dependencies :


```sh
$ composer install
$ npm install
```

### Available CLI commands
- `composer lint:wpcs` : checks all PHP files against [PHP Coding Standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/php/).
- `composer lint:php` : checks all PHP files for syntax errors.
- `composer make-pot` : generates a .pot file in the `languages/` directory.
- `npm run compile:css` : compiles SASS files to css.
- `npm run compile:rtl` : generates an RTL stylesheet.
- `npm run watch` : watches all SASS files and recompiles them to css when they change.
- `npm run lint:scss` : checks all SASS files against [CSS Coding Standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/css/).
- `npm run lint:js` : checks all JavaScript files against [JavaScript Coding Standards](https://developer.wordpress.org/coding-standards/wordpress-coding-standards/javascript/).
- `npm run bundle` : generates a .zip archive for distribution, excluding development and system files.

---
## Field Types
Follow this [LINK](https://hackmd.io/kRXbmm2IQ96Bo-kqCMSnqA#Basic) to find example implanmentations.

You can find a full reference of available settings on the [official ACF documentation](https://www.advancedcustomfields.com/resources/register-fields-via-php/#field-type%20settings).



### Blocks
***
#### File Structure

Create directory in the `blocks` directory found in the root directory and set up the below file Structure
```
WordPress/
├── wp-content/
│   ├── themes/
│   │   ├── theme-name/
│   │   │   └── blocks/
│   │   │       ├── example-block/
│   │   │       │   ├── view/
│   │   │       │   │   └── render.php
│   │   │       │   └── example-block.php
│   │   │       └── register-blocks.php
│   │   └── ...
│   └── ...
└── ...
```
- `render.php`: Contains the skeleton of the block view on the frontend
- `example-block.php`: This is the block class that contains the functionality and ACF Field of the Block

#### Register Block
To register a block add the class to `$classArray` in the  `register-blocks.php` found in `theme-name/blocks`.

:::spoiler {state="open"} Code
```php=
<?php
$classArray = [
	BlockNameBlock::class
];
```
:::
---
## Register ACF Fields to block
In the Block class with in the 'registerFields' function



### Simple Example
Below is a Simple implemention of use case
___
:::spoiler {state="open"} Code
```php=
<?php
$block = new FieldsBuilder('Block Name');
$block->setLocation('block', '==', 'acf/block-name-block');
$block->addGroup('block_name_block')
	->addText('text_field')
		->instructions('Instructions')
	->addRepeater('repeater')
	    ->addImage('image')
	->endRepeater()
->endGroup();

return $block->build();
```
:::

:::spoiler {state="open"} Output
```php=
<?php
return = [
    'key' => 'block_name',
    'title' => 'Block Name',
    'fields' => [
        [
            'key' => 'block_name_block',
            'label' => 'Block Name Block',
            'name' => 'block_name_block',
            'type' => 'group',
            'instructions' => '',
            'required' => 0,
            'conditional_logic' => 0,
            'wrapper' => [
                'width' => '',
                'class' => '',
                'id' => '',
            ],
            'layout' => 'block',
            'sub_fields' => [
                [
                    'key' => 'text_field',
                    'label' => 'Text Field',
                    'name' => 'text_field',
                    'type' => 'text',
                    'instructions' => 'Instructions',
                    'required' => 0,
                    'conditional_logic' => 0,
                    'wrapper' => [
                        'width' => '',
                        'class' => '',
                        'id' => '',
                    ],
                    'default_value' => '',
                    'placeholder' => '',
                    'prepend' => '',
                    'append' => '',
                    'maxlength' => '',
                ],
                [
                    'key' => 'repeater',
                    'label' => 'Repeater',
                    'name' => 'repeater',
                    'type' => 'repeater',
                    'instructions' => '',
                    'required' => 0,
                    'conditional_logic' => 0,
                    'wrapper' => [
                        'width' => '',
                        'class' => '',
                        'id' => '',
                    ],
                    'collapsed' => '',
                    'min' => 0,
                    'max' => 0,
                    'layout' => 'table',
                    'button_label' => '',
                    'sub_fields' => [
                        [
                            'key' => 'image',
                            'label' => 'Image',
                            'name' => 'image',
                            'type' => 'image',
                            'instructions' => '',
                            'required' => 0,
                            'conditional_logic' => 0,
                            'wrapper' => [
                                'width' => '',
                                'class' => '',
                                'id' => '',
                            ],
                            'return_format' => 'array',
                            'preview_size' => 'medium',
                            'library' => 'all',
                            'min_width' => '',
                            'min_height' => '',
                            'min_size' => '',
                            'max_width' => '',
                            'max_height' => '',
                            'max_size' => '',
                            'mime_types' => '',
                        ],
                    ],
                ],
            ],
        ],
    ],
    'location' => [
        [
            [
                'param' => 'post_type',
                'operator' => '==',
                'value' => 'post',
            ],
        ],
    ],
    'menu_order' => 0,
    'position' => 'normal',
    'style' => 'default',
    'label_placement' => 'top',
    'instruction_placement' => 'label',
    'hide_on_screen' => '',
    'active' => TRUE,
    'description' => '',
    'show_in_rest' => 0,
];
```
:::
---

#### Reusable Examples

Below is an example of the reusable case scenario

---
:::spoiler {state="open"} Code

```php=
<?php
$background = new FieldsBuilder('background');
$background
    ->addTab('Background')
    ->addImage('background_image')
    ->addTrueFalse('fixed')
        ->instructions("Check to add a parallax effect where the background image doesn't move when scrolling")
    ->addColorPicker('background_color');

$banner = new FieldsBuilder('banner');
$banner
    ->addTab('Content')
    ->addText('title')
    ->addWysiwyg('content')
    ->addFields($background)
    ->setLocation('post_type', '==', 'page');

$section = new FieldsBuilder('section');
$section
    ->addTab('Content')
    ->addText('section_title')
    ->addRepeater('columns', ['min' => 1, 'layout' => 'block'])
        ->addTab('Content')
        ->addText('title')
        ->addWysiwyg('content')
        ->addFields($background)
        ->endRepeater()
    ->addFields($background)
    ->setLocation('post_type', '==', 'page');

```
:::
---

## CPT (Custom Post Type)

### File Location

Create a class in the `cpt` directory found in the `include` directory.
```
WordPress/
├── wp-content/
│   ├── themes/
│   │   ├── include/
│   │   │   └── cpt/
│   │   │       └── example-cpt.php
│   │   └── ...
│   └── ...
└── ...
```

#### CPT Class Skeleton

In the CPT class file the below snippet is the basic structure

:::spoiler {state="open"} Code
```php=
<?php
namespace JBC\Include\CPT;
/**
 * Functions which enhance the theme by adding Custom Post Type (CPT) into WordPress
 *
 * @package Example_Theme
 */

class ExampleCPT {
    
    public function register() {
        $this->example_cpt();
        $this->example_cpt_categories();
        $this->example_cpt_template();
        $this->example_settings_menu();
        acf_add_local_field_group( $this->example_settings_acf() );
        acf_add_local_field_group( $this->example_categories_acf() );
    }
    
    public function example_cpt() {
        ...
    }
    
    private function example_cpt_categories() {
        ...
    }
    
    private function example_cpt_template() {
        ...
    }
    
    private function example_settings_menu() {
        ...
    }
    
    private function example_settings_acf() {
        ...
    }
    
    private function example_categories_acf() {
        ...
    }
}
```
:::

#### example_cpt()

Code example:

:::spoiler {state="open"} Code
```php=
<?php
public function example_cpt() {
	$supports = [
		'title', // post title
		'editor', // post content
		'author', // post author
		'thumbnail', // featured images
		'excerpt', // post excerpt
		'custom-fields', // custom fields
		'comments', // post comments
		'revisions', // post revisions
		'post-formats', // post formats
	];
	$labels   = [
		'name'           => _x( 'Examples', 'plural' ),
		'singular_name'  => _x( 'Example', 'singular' ),
		'menu_name'      => _x( 'Example', 'admin menu' ),
		'name_admin_bar' => _x( 'Example', 'admin bar' ),
		'add_new'        => _x( 'Add New', 'add new' ),
		'add_new_item'   => __( 'Add New Example' ),
		'new_item'       => __( 'New Example' ),
		'edit_item'      => __( 'Edit Example' ),
		'view_item'      => __( 'View Example' ),
		'all_items'      => __( 'All Examples' ),
		'search_items'   => __( 'Search Examples' ),
		'not_found'      => __( 'No Example found.' ),
	];
	$args     = [
		'supports'     => $supports,
		'labels'       => $labels,
		'public'       => TRUE,
		'query_var'    => TRUE,
		'rewrite'      => [ 'slug' => 'example' ],
		'has_archive'  => TRUE,
		'hierarchical' => FALSE,
	];
	register_post_type( 'example', $args );
}
```
:::

#### example_cpt_categories()

Code example:

:::spoiler {state="open"} Code
```php=
<?php 

private function example_cpt_categories() {
    $labels = [
        'name' => _x( 'Example Categories', 'taxonomy general name', 'example-theme' ),
        'singular_name'     => _x( 'Example Category', 'taxonomy singular name', 'example-theme' ),
        'search_items'      => __( 'Search Example Categories', 'example-theme' ),
        'all_items'         => __( 'All Example Categories', 'example-theme' ),
        'parent_item'       => __( 'Parent Example Category', 'example-theme' ),
        'parent_item_colon' => __( 'Parent Example Category:', 'example-theme' ),
        'edit_item'         => __( 'Edit Example Category', 'example-theme' ),
        'update_item'       => __( 'Update Example Category', 'example-theme' ),
        'add_new_item'      => __( 'Add New Example Category', 'example-theme' ),
        'new_item_name'     => __( 'New Example Category Name', 'example-theme' ),
        'menu_name'         => __( 'Example Category', 'example-theme' ),
    ];
    
    $args = [
        'hierarchical'      => TRUE,
        'labels'            => $labels,
        'show_ui'           => TRUE,
        'show_admin_column' => TRUE,
        'query_var'         => TRUE,
        'show_in_rest'      => TRUE,
    ];
    
    register_taxonomy( 'examples_categories', [ 'examples' ], $args );
}
```
:::

#### example_cpt_template()

Code example:

:::spoiler {state="open"} Code
```php=12
<?php 

private function example_cpt_template() {
    $page_type_object = get_post_type_object( 'examples' );
    $page_type_object->template = [
        [
            'acf/examples-block',
            [
                'data' => [
                    'examples-block_title'      => 'Related examples',
                    '"_examples-block_title'    => 'field_examples_block_examples-block_title',
                    'examples-block_sub_title'  => '',
                    '_examples-block_sub_title' => 'field_examples_block_examples-block_sub_title',
                    'examples-block_link'       => [
                        "title"  => 'All examples',
                        "url"    => '/examples',
                        "target" => '',
                    ],
                    '_examples-block_link'      => 'field_examples_block_examples-block_link',
                    'examples-block'            => '',
                    '_examples-block'           => 'field_examples_block_examples-block',
                ],
            ],
        ],
    ];
}
```
:::


#### example_settings_menu()

Code example:

:::spoiler {state="open"} Code
```php=
<?php
private function example_settings_menu() {
    if ( function_exists( 'acf_add_options_page' ) ) {
        acf_add_options_page( [
            'page_title'  => 'Examples Settings',
            'menu_slug'   => 'examples-settings',
            'menu_title'  => 'Setting',
            'parent_slug' => 'edit.php?post_type=examples',
        ] );
    }
}
```
:::

#### example_settings_acf()
Set up the same as the [Register ACF Fields to block](#Register-ACF-Fields-to-block) changing the location to the setting page.

Code example:

:::spoiler {state="open"} Code
```php=
<?php
private function example_settings_acf() {
    ...
    $block->setLocation( 'options_page', '==', 'examples-settings' );
    ...
}
```


#### example_categories_acf()
Set up the same as the [Register ACF Fields to block](#Register-ACF-Fields-to-block) changing the location to the categories.

Code example:

:::spoiler {state="open"} Code
```php=
<?php
private function example_categories_acf() {
    ...
    $block ->setLocation( 'taxonomy', '==', 'examples_categories' );
    ...
}
```


#### Register CPT
To register a CPT add the class to `getCptList()` return array in the  `register-cpt.php` found in `theme-name/include`.
:::spoiler {state="open"} Code
```php=
<?php
function getCptList(): array {
    return [
        ExampleCPT::class
    ];
}
```
:::
---

