├── js └── column.js ├── .gitignore ├── css └── column.css ├── classes └── Column │ ├── Export.php │ ├── Sorting.php │ ├── Editing.php │ ├── Search.php │ └── Column.php ├── readme.txt ├── languages └── ac-column-template.po ├── ac-column-template.php └── README.md /js/column.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | .idea -------------------------------------------------------------------------------- /css/column.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Column 3 | * ---------------------------------------------------------------------------- 4 | */ 5 | .column-ac-COLUMN_NAME { 6 | 7 | } -------------------------------------------------------------------------------- /classes/Column/Export.php: -------------------------------------------------------------------------------- 1 | \n" 8 | "Language-Team: AUTHOR_NAME\n" 9 | "Language: en\n" 10 | "MIME-Version: 1.0\n" 11 | "Content-Type: text/plain; charset=UTF-8\n" 12 | "Content-Transfer-Encoding: 8bit\n" 13 | "X-Poedit-KeywordsList: __;_e\n" 14 | "X-Poedit-Basepath: .\n" 15 | "X-Poedit-SourceCharset: UTF-8\n" 16 | "X-Generator: Poedit 1.7.3\n" 17 | "Plural-Forms: nplurals=2; plural=(n != 1);\n" 18 | "X-Poedit-SearchPath-0: ..\n" 19 | "X-Poedit-SearchPath-1: .\n" 20 | "X-Poedit-SearchPathExcluded-0: ../codepress-admin-columns\n" 21 | 22 | #: ../cac-column-COLUMN_NAME.php:18 23 | msgid "COLUMN_LABEL" 24 | msgstr "" 25 | 26 | #, fuzzy 27 | #~ msgid "Pro add-on" 28 | #~ msgstr "Get Admin Columns Pro" 29 | 30 | #, fuzzy 31 | #~ msgid "Add-ons updates" 32 | #~ msgstr "Add-ons" 33 | -------------------------------------------------------------------------------- /ac-column-template.php: -------------------------------------------------------------------------------- 1 | get_version()->is_lte(new AC\Plugin\Version('6.3'))) { 16 | return; 17 | } 18 | 19 | // Load necessary files 20 | require_once __DIR__ . '/classes/Column/Column.php'; 21 | require_once __DIR__ . '/classes/Column/Editing.php'; 22 | require_once __DIR__ . '/classes/Column/Export.php'; 23 | require_once __DIR__ . '/classes/Column/Search.php'; 24 | require_once __DIR__ . '/classes/Column/Sorting.php'; 25 | 26 | // Make your custom column available to a specific WordPress list table: 27 | 28 | // Example #1 - for the custom post type 'page' 29 | if ('page' === $list_screen->get_key()) { 30 | // Register column 31 | $list_screen->register_column_type( 32 | new AcColumnTemplate\Column\Column() 33 | ); 34 | } 35 | 36 | // Example #2 - for media 37 | // if ( 'attachment' === $list_screen->get_key() ) { 38 | // Register column 39 | // } 40 | 41 | // Example #3 - for all post types 42 | // if ( AC\MetaType::POST === $list_screen->get_meta_type() ) { 43 | // Register column 44 | // } 45 | 46 | // Example #4 - for users 47 | // if ( AC\MetaType::USER === $list_screen->get_meta_type() ) { 48 | // Register column 49 | // } 50 | 51 | // Example #4 - for categories on the taxonomy list table 52 | // if ( $list_screen instanceof ACP\ListScreen\Taxonomy && 'category' === $list_screen->get_taxonomy()) { 53 | // Register column 54 | // } 55 | 56 | }); 57 | 58 | // 2. Optionally: load a text domain 59 | // load_plugin_textdomain('ac-column-template', false, __DIR__ . '/languages/'); 60 | -------------------------------------------------------------------------------- /classes/Column/Sorting.php: -------------------------------------------------------------------------------- 1 | join( 27 | "LEFT JOIN $wpdb->postmeta AS ac_sort ON $wpdb->posts.ID = ac_sort.post_id 28 | AND ac_sort.meta_key = 'my_custom_field_key'" 29 | ); 30 | 31 | // 2. Set the 'ORDER BY' statement: 32 | $bindings->order_by( 33 | "ac_sort.meta_value " . $order 34 | ); 35 | 36 | // 2. Optionally: if you want your empty results at the bottom, you can 37 | // use this factory which will create the correct 'ORDER BY' statement for you 38 | $bindings->order_by( 39 | SqlOrderByFactory::create("ac_sort.meta_value", $order) 40 | ); 41 | 42 | // 3. Optionally: set the 'GROUP BY' to groups the results 43 | $bindings->group_by( 44 | "$wpdb->posts.ID" 45 | ); 46 | 47 | /** 48 | * The created Query Bindings will be parsed into SQL by one of these services: 49 | * @see \ACP\Query\Post This service injects the SQL bindings into `WP_Query` 50 | * @see \ACP\Query\User This service injects the SQL bindings into `WP_User_Query` 51 | * @see \ACP\Query\Term This service injects the SQL bindings into `WP_Term_Query` 52 | * @see \ACP\Query\Comment This service injects the SQL bindings into `WP_Comment_Query` 53 | */ 54 | return $bindings; 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Admin Columns - Column Template 2 | 3 | Welcome to the Admin Columns Pro column template repository. 4 | Here you will find a starter-kit for creating a new column for Admin Columns Pro. This starter-kit will work as a normal WP plugin. 5 | 6 | For more information about creating a new column type, please read the following article: 7 | https://docs.admincolumns.com/article/21-how-to-create-my-own-column 8 | 9 | This template is for Admin Columns Pro only. 10 | 11 | ### Structure 12 | 13 | * `ac-column-template.php`: Main plugin file that registers the column 14 | * `/classes/Column/Column.php`: Column class with all column logic 15 | * `/classes/Column/Editing.php`: Example of a Editing Model (used by inline- and bulk-editing) 16 | * `/classes/Column/Export.php`: Example of a Export Model (used by exporting to generate a CSV) 17 | * `/classes/Column/Search.php`: Example of a Smart Filtering Model (makes the column filterable) 18 | * `/classes/Column/Sorting.php`: Example of a Sorting Model (makes the column sortable) 19 | * `/css`: folder for .css files 20 | * `/js`: folder for .js files 21 | * `/languages`: folder for .pot, .po and .mo files 22 | * `readme.txt`: WordPress readme file to be used by the WordPress repository 23 | 24 | ### step 1. 25 | 26 | This template uses two placeholders. Use the following list to do a 'find and replace' on them: 27 | 28 | * `COLUMN_NAME`: Single-word, no spaces. Underscores allowed. eg. my-custom-column-name 29 | * `COLUMN_LABEL`: Multiple words, can include spaces, visible when selecting a column 30 | 31 | ### step 2. 32 | 33 | Edit the `ac-column-template.php` file to change which list table the column belongs too. 34 | 35 | ### step 3. 36 | 37 | Edit the `Column.php` file and include your custom code in the appropriate functions. 38 | 39 | ### step 4 (optional). 40 | 41 | The structure of this plugin is prepared so that it can contain multiple columns. 42 | If you want to create multiple custom columns in this plugin, you can create a copy of the 'Column' folder and use a 43 | different folder name. Then make sure to `require` the copied files in the main plugin file. -------------------------------------------------------------------------------- /classes/Column/Editing.php: -------------------------------------------------------------------------------- 1 | 'Option #1', 2 => 'Option #2']); 57 | 58 | // (Optional) use View specific modifiers 59 | //$view->set_clear_button( true ); 60 | //$view->set_placeholder( 'Custom placeholder' ); 61 | //$view->set_required( true ); 62 | 63 | // (Optional) return a different view or disable editing based on context: 'bulk' or 'single' (index) 64 | // return $context === 'bulk' ? $view : null; 65 | 66 | return $view; 67 | } 68 | 69 | /** 70 | * Saves the value after using inline or bulk-edit 71 | * 72 | * @param int $id Object ID 73 | * @param mixed $data Value to be saved 74 | */ 75 | public function update(int $id, $data): void 76 | { 77 | // Store the value that has been entered with inline or bulk-edit 78 | // For example: 79 | update_post_meta($id, 'my_custom_field_key', $data); 80 | } 81 | 82 | } -------------------------------------------------------------------------------- /classes/Column/Search.php: -------------------------------------------------------------------------------- 1 | meta_query([ 58 | 'key' => 'my_custom_field_key', 59 | 'value' => $value->get_value(), 60 | 'compare' => $operator, 61 | ]); 62 | 63 | /** 64 | * Example #2 - altering the query with custom SQL 65 | * @see Query\Post This service handler parses the SQL bindings into `WP_Query` 66 | * @see WP_Query::get_posts This object runs the SQL query 67 | */ 68 | global $wpdb; 69 | 70 | // 1. You can 'JOIN' tables together like so: 71 | $binding->join( 72 | "INNER JOIN $wpdb->postmeta AS ac_filter ON $wpdb->posts.ID = ac_filter.post_id 73 | AND ac_filter.meta_key = 'my_custom_field_key'" 74 | ); 75 | 76 | // 2. Create the `WHERE` clause. Use the `ComparisonFactory` to create a where-statement by operator (equal, contains etc.) 77 | $where = ComparisonFactory::create( 78 | 'ac_filter.meta_value', 79 | $operator, 80 | $value 81 | )->prepare(); 82 | 83 | $binding->where($where); 84 | 85 | /** 86 | * The created Query Bindings will be parsed into SQL by one of these services: 87 | * @see \ACP\Query\Post This service injects the SQL bindings into `WP_Query` 88 | * @see \ACP\Query\User This service injects the SQL bindings into `WP_User_Query` 89 | * @see \ACP\Query\Term This service injects the SQL bindings into `WP_Term_Query` 90 | * @see \ACP\Query\Comment This service injects the SQL bindings into `WP_Comment_Query` 91 | */ 92 | return $binding; 93 | } 94 | 95 | } -------------------------------------------------------------------------------- /classes/Column/Column.php: -------------------------------------------------------------------------------- 1 | set_type('ac-COLUMN_NAME'); 20 | 21 | // Default column label. 22 | $this->set_label(__('COLUMN_LABEL', 'ac-column-template')); 23 | } 24 | 25 | /** 26 | * Display value. Returns the column value used for rendering within the list table. 27 | */ 28 | public function get_value($id): string 29 | { 30 | // put all the column logic here to retrieve the value you need 31 | // For example: 32 | $value = get_post_meta($id, 'my_custom_field_key', true) ?: '-'; 33 | 34 | // Optionally you can change the display of the value. In this example we added an edit post link. 35 | $value = "$value"; 36 | 37 | return $value; 38 | } 39 | 40 | /** 41 | * Editing model. Used by inline- and bulk-editing to update column values directly from within the list table. 42 | * @link https://docs.admincolumns.com/article/27-how-to-use-inline-editing 43 | * @link https://docs.admincolumns.com/article/67-how-to-use-bulk-editing 44 | */ 45 | public function editing() 46 | { 47 | /** 48 | * Example #1 - A custom editing model. Create your own input field and set how you want your data to be saved 49 | */ 50 | return new Editing(); 51 | 52 | /** 53 | * Example #2 - A `Text` input field for a custom field value 54 | * @see ACP\Editing\Service\Post\Meta This model stores the data as metadata 55 | * @see ACP\Editing\View\Text Type of input field 56 | */ 57 | // return new ACP\Editing\Service\Post\Meta('my_custom_field_key', new ACP\Editing\View\Text()); 58 | } 59 | 60 | /** 61 | * Sorting model. Used to sort the list table when clicking the column header. 62 | * @link https://docs.admincolumns.com/article/34-how-to-enable-sorting 63 | */ 64 | public function sorting() 65 | { 66 | /** 67 | * Example #1 - Write your own custom sorting query using this model 68 | */ 69 | return new Sorting(); 70 | 71 | /** 72 | * Example #2 - Sorting by custom field values on the posts table 73 | * @see ACP\Sorting\Model\Post\Meta 74 | */ 75 | // return new ACP\Sorting\Model\Post\Meta('my_custom_field_key'); 76 | 77 | /** 78 | * Example #3 - Sorting by numeric custom field values on the users table 79 | * @see ACP\Sorting\Model\User\Meta 80 | */ 81 | // return new ACP\Sorting\Model\User\Meta( 'my_custom_field_key', new ACP\Sorting\Type\DataType( 'numeric' ) ); 82 | 83 | /** 84 | * Example #4 - Sorting by custom field values on the posts table with custom formatting applied. 85 | * In this example we want to sort by the Post `Title`, not the Post `ID` that is stored within the custom field. 86 | * We will convert each Post `ID` to a Post `Title` before we apply sorting. 87 | * @see ACP\Sorting\Model\Post\MetaFormat 88 | */ 89 | // return new ACP\Sorting\Model\Post\MetaFormat( new ACP\Sorting\FormatValue\PostTitle(), 'my_custom_field_key' ); 90 | /** 91 | * You will find all available sorting models in this plugin folder: `admin-columns-pro/classes/Sorting/Model`. 92 | */ 93 | } 94 | 95 | /** 96 | * Export model. Used for exporting column values to CSV. 97 | * @link https://docs.admincolumns.com/article/69-how-to-use-export 98 | */ 99 | public function export() 100 | { 101 | /** 102 | * Example #1 - A custom export model 103 | */ 104 | return new Export(); 105 | 106 | /** 107 | * Example #2 - Export a custom field value 108 | * @see ACP\Export\Model\Post\Meta 109 | * @see ACP\Export\Model\User\Meta 110 | * @see ACP\Export\Model\Term\Meta 111 | * @see ACP\Export\Model\Comment\Meta 112 | */ 113 | // return new ACP\Export\Model\Post\Meta('my_custom_field_key'); 114 | // return new ACP\Export\Model\User\Meta('my_custom_field_key'); 115 | // return new ACP\Export\Model\Meta\Meta('my_custom_field_key'); 116 | // return new ACP\Export\Model\Comment\Meta('my_custom_field_key'); 117 | } 118 | 119 | /** 120 | * Smart Filtering model (internally named: Search). Used to filter the list table when using our smart filters. 121 | * @link https://docs.admincolumns.com/article/61-how-to-use-smart-filtering 122 | */ 123 | public function search() 124 | { 125 | /** 126 | * Example #1 - A custom filtering model 127 | */ 128 | return new Search(); 129 | 130 | /** 131 | * Example #2 - Filter by custom field values 132 | */ 133 | // return new ACP\Search\Comparison\Meta\Text('my_custom_field_key'); 134 | // return new ACP\Search\Comparison\Meta\Number('my_custom_field_key'); 135 | /** 136 | * Available custom field filtering models: 137 | * @see ACP\Search\Comparison\Meta\Text 138 | * @see ACP\Search\Comparison\Meta\Number 139 | * @see ACP\Search\Comparison\Meta\Image 140 | * @see ACP\Search\Comparison\Meta\Toggle 141 | * @see ACP\Search\Comparison\Meta\Date 142 | * @see ACP\Search\Comparison\Meta\DateTime\ISO 143 | * @see ACP\Search\Comparison\Meta\DateTime\Timestamp 144 | * @see ACP\Search\Comparison\Meta\User 145 | * @see ACP\Search\Comparison\Meta\Post 146 | * @see ACP\Search\Comparison\Meta\Media 147 | * @see ACP\Search\Comparison\Meta\Decimal 148 | * @see ACP\Search\Comparison\Meta\Select 149 | * @see ACP\Search\Comparison\Meta\Checkmark 150 | * @see ACP\Search\Comparison\Meta\Serialized 151 | */ 152 | } 153 | 154 | /** 155 | * (Optional) Create extra settings for you column. These are visible when editing a column. You can remove this function is you do not use it! 156 | * Write your own settings or use any of the standard available settings. 157 | */ 158 | protected function register_settings(): void 159 | { 160 | // NOTE! When you use any of these settings, you should remove the get_value() method from this column, because the value will be rendered by the AC_Settings_Column_{$type} classes. 161 | 162 | // Display an image preview size settings screen 163 | // $this->add_setting( new AC\Settings\Column\Image( $this ) ); 164 | 165 | // Display an excerpt length input field in words 166 | // $this->add_setting( new AC\Settings\Column\WordLimit( $this ) ); 167 | 168 | // Display an excerpt length input field in characters 169 | // $this->add_setting( new AC\Settings\Column\CharacterLimit( $this ) ); 170 | 171 | // Display a date format settings input field 172 | // $this->add_setting( new AC\Settings\Column\Date( $this ) ); 173 | 174 | // Display before and after input fields 175 | // $this->add_setting( new AC\Settings\Column\BeforeAfter( $this ) ); 176 | 177 | // Displays a dropdown menu with user display formats 178 | // $this->add_setting( new AC\Settings\Column\User( $this ) ); 179 | 180 | // Displays a dropdown menu with post display formats 181 | // $this->add_setting( new AC\Settings\Column\Post( $this ) ); 182 | } 183 | 184 | /** 185 | * (Optional) Is valid. You can remove this function if you do not use it! 186 | * This determines whether the column should be available. If you want to disable this column 187 | * for a particular post type you can set this to false. 188 | * @return bool True/False Default should be 'true'. 189 | */ 190 | public function is_valid(): bool 191 | { 192 | // Example: if the post type does not support thumbnails then return false 193 | // if ( ! post_type_supports( $this->get_post_type(), 'thumbnail' ) ) { 194 | // return false; 195 | // } 196 | 197 | return true; 198 | } 199 | 200 | /* 201 | * (Optional) Enqueue CSS + JavaScript on the admin listings screen. You can remove this function is you do not use it! 202 | * 203 | * This action is called in the admin_head action on the listings screen where your column values are displayed. 204 | * Use this action to add CSS + JavaScript 205 | */ 206 | public function scripts(): void 207 | { 208 | // wp_enqueue_script('script-' . $this->get_name(), plugin_dir_url(AC_CT_FILE) . "js/column.js"); 209 | // wp_enqueue_style('style-' . $this->get_name(), plugin_dir_url(AC_CT_FILE) . "css/column.css"); 210 | } 211 | 212 | } --------------------------------------------------------------------------------