├── screenshots
├── screenshot-1.png
├── screenshot-2.png
├── screenshot-4.png
├── screenshot-5.png
├── screenshot-3-1.png
└── screenshot-3-2.png
├── languages
├── mc-acf-ft-template-fr_FR.mo
└── mc-acf-ft-template-fr_FR.po
├── .github
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── composer.json
├── assets
├── css
│ └── mc-acf-ft-css.css
└── js
│ └── mc-acf-ft-template.js
├── mc-acf-flexible-template.php
├── readme.md
└── includes
├── mc-acf-ft-register-cpt.php
└── class-mc-acf-flexible-template.php
/screenshots/screenshot-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarieComet/mc-acf-flexible-template/HEAD/screenshots/screenshot-1.png
--------------------------------------------------------------------------------
/screenshots/screenshot-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarieComet/mc-acf-flexible-template/HEAD/screenshots/screenshot-2.png
--------------------------------------------------------------------------------
/screenshots/screenshot-4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarieComet/mc-acf-flexible-template/HEAD/screenshots/screenshot-4.png
--------------------------------------------------------------------------------
/screenshots/screenshot-5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarieComet/mc-acf-flexible-template/HEAD/screenshots/screenshot-5.png
--------------------------------------------------------------------------------
/screenshots/screenshot-3-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarieComet/mc-acf-flexible-template/HEAD/screenshots/screenshot-3-1.png
--------------------------------------------------------------------------------
/screenshots/screenshot-3-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarieComet/mc-acf-flexible-template/HEAD/screenshots/screenshot-3-2.png
--------------------------------------------------------------------------------
/languages/mc-acf-ft-template-fr_FR.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MarieComet/mc-acf-flexible-template/HEAD/languages/mc-acf-ft-template-fr_FR.mo
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 |
5 | ---
6 |
7 | **Describe the bug**
8 | A clear and concise description of what the bug is.
9 |
10 | **To Reproduce**
11 | Steps to reproduce the behavior:
12 |
13 | **Expected behavior**
14 | A clear and concise description of what you expected to happen.
15 |
16 | **Screenshots**
17 | If applicable, add screenshots to help explain your problem.
18 |
19 | **WordPress and ACF Versions**
20 | WordPress version :
21 | ACF version:
22 | ACF Pro version:
23 | ACF add-ons:
24 |
25 | **Please share an export of your ACF fields groups**
26 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 |
5 | ---
6 |
7 | **Is your feature request related to a problem? Please describe.**
8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9 |
10 | **Describe the solution you'd like**
11 | A clear and concise description of what you want to happen.
12 |
13 | **Describe alternatives you've considered**
14 | A clear and concise description of any alternative solutions or features you've considered.
15 |
16 | **Additional context**
17 | Add any other context or screenshots about the feature request here.
18 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name" : "mariecomet/mc-acf-flexible-template",
3 | "description" : "Makes it possible to save the ACF flexible content fields as templates and to use them again.",
4 | "keywords" : ["wordpress"],
5 | "homepage" : "https://github.com/MarieComet/mc-acf-flexible-template",
6 | "license" : "GPL-2.0-or-later",
7 | "type" : "wordpress-plugin",
8 | "authors" : [
9 | {
10 | "name" : "Marie Comet",
11 | "homepage" : "https://www.mariecomet.fr"
12 | }
13 | ],
14 | "require" : {
15 | "composer/installers" : "^1.0",
16 | "php" : ">=5.3.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/assets/css/mc-acf-ft-css.css:
--------------------------------------------------------------------------------
1 | .acf-mc-ft-wrap {
2 | text-align: right;
3 | }
4 | .acf-mc-ft-wrap .popup {
5 | display: none;
6 | padding: 1.5em;
7 | right: 0;
8 | text-align: left;
9 | font-weight: normal;
10 | width: 350px;
11 | }
12 | .acf-field .acf-mc-ft-wrap .popup label {
13 | margin-bottom: 1.5em;
14 | }
15 | button.mc-open {
16 | font-weight: normal;
17 | }
18 | button.handlediv.acf-mc-ft-close {
19 | width: 15px;
20 | height: 15px;
21 | position: absolute;
22 | right: 10px;
23 | top: 10px;
24 | }
25 | button.handlediv.acf-mc-ft-close:hover {
26 | color: #fff;
27 | }
28 | .acf-mc-ft-save-wrap {
29 | margin: 1.2em 0;
30 | }
31 | .acf-mc-ft-save-wrap h3 {
32 | text-align: right;
33 | font-weight: normal;
34 | }
35 | .acf-mc-ft-save-wrap input[type="text"].acf-mc-ft-template-name, .acf-mc-import-content select.acf-templates-select, .acf-mc-ft-save-wrap select.acf-templates-terms-select {
36 | width: 100%;
37 | vertical-align: bottom;
38 | margin-right: 0.5em;
39 | min-width: 300px;
40 | }
41 | .acf-mc-ft-save-wrap input[type="text"].acf-mc-ft-template-name, .acf-mc-save-content .select2, .acf-mc-import-content .select2 {
42 | margin-top: 0.5em;
43 | color: #383838;
44 | font-weight: normal;
45 | background-color: #fff;
46 | }
47 | .acf-mc-import-content select.acf-templates-select, .acf-mc-ft-save-wrap select.acf-templates-terms-select {
48 | min-width: 341px;
49 | }
50 | .acf-mc-ft-replace-content {
51 | margin-bottom: 15px;
52 | }
53 | .acf-mc-ft-wrap .acf-success-message {
54 | display: none;
55 | border: 2px solid #46b450;
56 | border-radius: 3px;
57 | padding: 4px 7px;
58 | margin-bottom: 10px;
59 | background-color: #fff;
60 | color: #2f353e;
61 | }
62 | .acf-flexible-content .layout.just-added.bg-green {
63 | border-top: 2px solid rgba(27, 193, 41, 0.5);
64 | }
65 |
--------------------------------------------------------------------------------
/mc-acf-flexible-template.php:
--------------------------------------------------------------------------------
1 | = 0 ) {
47 | $outdated_version = false;
48 | }
49 |
50 | /* Check transient, if available display notice */
51 | if ( get_transient( 'mc-acf-admin-notice' ) && ! class_exists('acf') ) {
52 | ?>
53 |
56 |
64 |
67 | 1` in the options of this last one (after min, max and button_label options)
22 | * Export and Import will show on your flexible fields.
23 | * You can edit your templates in admin > ACF Templates.
24 | * See screenshots.
25 |
26 | ## FAQ
27 |
28 | ### Export and import buttons don't show on my flexible field
29 |
30 | * Sometime it's necessary to turn on / off option twice.
31 |
32 | ### How to define which type of user has access to these features?
33 |
34 | * There is two filters you can use for that :
35 | `mc_ft_import_cap` and `mc_ft_save_cap` which you must pass one or more WordPress capabilities.
36 |
37 | ### How to customize labels used in admin templates?
38 |
39 | * Because Flexible fields can be very different things depending on the projects, you can use 4 filters to customize the labels used in admin, and also textdomain :
40 | `mc_ft_template_plural`, `mc_ft_template_singular` and `mc_ft_template_all_menu_label`.
41 | Examples of how to use them :
42 | ```
43 | // singular label
44 | function my_custom_template_sing_label( $singular_name ) {
45 | $singular_name = __( 'Custom singular', 'my-text-domain' );
46 | return $singular_name;
47 | }
48 | add_filter( 'mc_ft_template_singular', 'my_custom_template_sing_label', 10, 1 );
49 |
50 | // plural label
51 | function my_custom_template_plur_label( $plural_name ) {
52 | $plural_name = __( 'Custom plural','my-text-domain' );
53 | return $plural_name;
54 | }
55 | add_filter( 'mc_ft_template_plural', 'my_custom_template_plur_label', 10, 1 );
56 |
57 | // the "all" menu label
58 | function my_custom_template_menu_label( $all_menu_label ) {
59 | $all_menu_label = __( 'Custom "all" menu label', 'my-text-domain' );
60 | return $all_menu_label;
61 | }
62 | add_filter( 'mc_ft_template_all_menu_label', 'my_custom_template_menu_label', 10, 1 );
63 | ```
64 |
65 | ## Screenshots
66 |
67 | * Flexible field setting
68 | 
69 |
70 | * Save flexible layouts as template
71 | 
72 |
73 | * Import flexible template
74 | 
75 |
76 | * Flexible template imported
77 | 
78 |
79 | * Flexibles templates list
80 | 
81 |
82 | * Edit existing template
83 | 
84 |
85 | ### History
86 |
87 | ### 2017-12-23 1.0.1
88 | * Initial Commit
89 |
90 | ### 2018-01-04 1.0.2
91 | * Add edit templates functionnality
92 | * Add filters to edit admin labels
93 |
94 | ### 2018-07-14 1.1.0
95 | * Update for ACF 5.7.0 JS API changes
96 | * Important : require at LEAST ACF 5.7.0
97 |
98 | ### 2018-11-01
99 | * Add new feature "replace existing content" before import. Thanks @virgo79 !
100 |
101 | ### March 13 2020
102 | * Tested with WordPress 5.3.2 and ACF Pro 5.8.7.
103 |
104 | ### October 21 2021 1.1.1
105 | * Allow html tags in acf field label (https://github.com/MarieComet/mc-acf-flexible-template/issues/23)
--------------------------------------------------------------------------------
/includes/mc-acf-ft-register-cpt.php:
--------------------------------------------------------------------------------
1 | $plural_name,
23 | 'singular_name' => $singular_name,
24 | 'menu_name' => $plural_name,
25 | 'name_admin_bar' => $singular_name,
26 | 'archives' => __( 'ACF Template Archives', 'mc-acf-ft-template' ),
27 | 'attributes' => __( 'ACF Template Attributes', 'mc-acf-ft-template' ),
28 | 'parent_item_colon' => __( 'Parent Item:', 'mc-acf-ft-template' ),
29 | 'all_items' => $all_menu_label,
30 | 'add_new_item' => __( 'Add New Item', 'mc-acf-ft-template' ),
31 | 'add_new' => __( 'Add New', 'mc-acf-ft-template' ),
32 | 'new_item' => __( 'New Item', 'mc-acf-ft-template' ),
33 | 'edit_item' => __( 'Edit Item', 'mc-acf-ft-template' ),
34 | 'update_item' => __( 'Update Item', 'mc-acf-ft-template' ),
35 | 'view_item' => __( 'View Item', 'mc-acf-ft-template' ),
36 | 'view_items' => __( 'View Items', 'mc-acf-ft-template' ),
37 | 'search_items' => __( 'Search Item', 'mc-acf-ft-template' ),
38 | 'not_found' => __( 'Not found', 'mc-acf-ft-template' ),
39 | 'not_found_in_trash' => __( 'Not found in Trash', 'mc-acf-ft-template' ),
40 | 'featured_image' => __( 'Featured Image', 'mc-acf-ft-template' ),
41 | 'set_featured_image' => __( 'Set featured image', 'mc-acf-ft-template' ),
42 | 'remove_featured_image' => __( 'Remove featured image', 'mc-acf-ft-template' ),
43 | 'use_featured_image' => __( 'Use as featured image', 'mc-acf-ft-template' ),
44 | 'insert_into_item' => __( 'Insert into item', 'mc-acf-ft-template' ),
45 | 'uploaded_to_this_item' => __( 'Uploaded to this item', 'mc-acf-ft-template' ),
46 | 'items_list' => __( 'Items list', 'mc-acf-ft-template' ),
47 | 'items_list_navigation' => __( 'Items list navigation', 'mc-acf-ft-template' ),
48 | 'filter_items_list' => __( 'Filter items list', 'mc-acf-ft-template' ),
49 | );
50 | $args = array(
51 | 'label' => __( 'ACF Template', 'mc-acf-ft-template' ),
52 | 'description' => __( 'ACF Template', 'mc-acf-ft-template' ),
53 | 'labels' => $labels,
54 | 'supports' => array( 'title', 'custom-fields' ),
55 | 'hierarchical' => false,
56 | 'public' => false,
57 | 'show_ui' => true,
58 | 'show_in_menu' => true,
59 | 'menu_position' => 80,
60 | 'menu_icon' => 'dashicons-layout',
61 | 'show_in_admin_bar' => false,
62 | 'show_in_nav_menus' => false,
63 | 'can_export' => true,
64 | 'has_archive' => false,
65 | 'exclude_from_search' => true,
66 | 'publicly_queryable' => false,
67 | 'map_meta_cap' => true,
68 | 'capability_type' => 'post',
69 | 'capabilities' => array(
70 | 'create_posts' => false,
71 | // Removes support for the "Add New" function ( use 'do_not_allow' instead of false for multisite set ups )
72 | ),
73 | 'show_in_rest' => true,
74 | );
75 | register_post_type( 'acf_template', $args );
76 |
77 | }
78 | add_action( 'init', 'mc_acf_ft_register_cpt', 0 );
79 |
80 | // Register Custom Taxonomy
81 | function mc_acf_ft_register_tax() {
82 |
83 | $labels = array(
84 | 'name' => _x( 'Categories', 'Taxonomy General Name', 'mc-acf-ft-template' ),
85 | 'singular_name' => _x( 'Category', 'Taxonomy Singular Name', 'mc-acf-ft-template' ),
86 | 'menu_name' => __( 'Categories', 'mc-acf-ft-template' ),
87 | 'all_items' => __( 'Categories', 'mc-acf-ft-template' ),
88 | 'parent_item' => __( 'Parent Item', 'mc-acf-ft-template' ),
89 | 'parent_item_colon' => __( 'Parent Item:', 'mc-acf-ft-template' ),
90 | 'new_item_name' => __( 'New Item Name', 'mc-acf-ft-template' ),
91 | 'add_new_item' => __( 'Add New Item', 'mc-acf-ft-template' ),
92 | 'edit_item' => __( 'Edit Item', 'mc-acf-ft-template' ),
93 | 'update_item' => __( 'Update Item', 'mc-acf-ft-template' ),
94 | 'view_item' => __( 'View Item', 'mc-acf-ft-template' ),
95 | 'separate_items_with_commas' => __( 'Separate items with commas', 'mc-acf-ft-template' ),
96 | 'add_or_remove_items' => __( 'Add or remove items', 'mc-acf-ft-template' ),
97 | 'choose_from_most_used' => __( 'Choose from the most used', 'mc-acf-ft-template' ),
98 | 'popular_items' => __( 'Popular Items', 'mc-acf-ft-template' ),
99 | 'search_items' => __( 'Search Items', 'mc-acf-ft-template' ),
100 | 'not_found' => __( 'Not Found', 'mc-acf-ft-template' ),
101 | 'no_terms' => __( 'No items', 'mc-acf-ft-template' ),
102 | 'items_list' => __( 'Items list', 'mc-acf-ft-template' ),
103 | 'items_list_navigation' => __( 'Items list navigation', 'mc-acf-ft-template' ),
104 | );
105 | $args = array(
106 | 'labels' => $labels,
107 | 'hierarchical' => true,
108 | 'public' => false,
109 | 'show_ui' => true,
110 | 'show_admin_column' => true,
111 | 'show_in_nav_menus' => false,
112 | 'show_tagcloud' => false,
113 | 'rewrite' => false,
114 | 'show_in_rest' => true,
115 | );
116 | register_taxonomy( 'acf_template_tax', array( 'acf_template' ), $args );
117 | }
118 | add_action( 'init', 'mc_acf_ft_register_tax', 0 );
119 |
120 | // Register custom column in admin
121 |
122 | add_filter( 'manage_acf_template_posts_columns', 'set_custom_edit_acf_template_columns' );
123 | add_action( 'manage_acf_template_posts_custom_column' , 'custom_acf_template_column', 10, 2 );
124 |
125 | function set_custom_edit_acf_template_columns( $columns ) {
126 | $columns['acf_template_group'] = __( 'Saved from field :', 'mc-acf-ft-template' );
127 | return $columns;
128 | }
129 |
130 | function custom_acf_template_column( $column, $post_id ) {
131 | switch ( $column ) {
132 |
133 | case 'acf_template_group' :
134 | $layout_parent_key = get_post_meta($post_id, '_flex_layout_parent', true );
135 | $layout_parent_obj = get_field_object($layout_parent_key);
136 | if ( $layout_parent_obj )
137 | echo $layout_parent_obj['label'];
138 | else
139 | _e( 'Unable to get parent flexible', 'mc-acf-ft-template' );
140 | break;
141 | }
142 | }
143 |
144 | function mc_acf_ft_rule_type( $choices ) {
145 |
146 | if ( isset( $choices['acf_template'] ) ) {
147 | unset( $choices['acf_template'] );
148 | }
149 | return $choices;
150 | }
151 | add_filter( 'acf/location/rule_values', 'mc_acf_ft_rule_type' );
--------------------------------------------------------------------------------
/languages/mc-acf-ft-template-fr_FR.po:
--------------------------------------------------------------------------------
1 | msgid ""
2 | msgstr ""
3 | "Project-Id-Version: MC ACF Flexible Template\n"
4 | "POT-Creation-Date: 2018-01-04 09:55+0100\n"
5 | "PO-Revision-Date: 2018-01-04 09:57+0100\n"
6 | "Last-Translator: \n"
7 | "Language-Team: Marie Comet \n"
8 | "Language: fr_FR\n"
9 | "MIME-Version: 1.0\n"
10 | "Content-Type: text/plain; charset=UTF-8\n"
11 | "Content-Transfer-Encoding: 8bit\n"
12 | "X-Generator: Poedit 1.8.7\n"
13 | "X-Poedit-Basepath: ..\n"
14 | "Plural-Forms: nplurals=2; plural=(n > 1);\n"
15 | "X-Poedit-SourceCharset: UTF-8\n"
16 | "X-Poedit-KeywordsList: _e;__;_x\n"
17 | "X-Poedit-SearchPath-0: .\n"
18 |
19 | #: includes/mc-acf-ft-class.php:81
20 | msgid "Save and load templates functionality"
21 | msgstr "Fonctionnalité de sauvegarde et chargement des modèles"
22 |
23 | #: includes/mc-acf-ft-class.php:82
24 | msgid "This flexible field should display save/load functionnality ?"
25 | msgstr ""
26 | "Souhaitez-vous afficher la fonctionnalité de sauvegarde/chargement de "
27 | "modèles ?"
28 |
29 | #: includes/mc-acf-ft-class.php:147
30 | msgid "Load template"
31 | msgstr "Charger un modèle"
32 |
33 | #: includes/mc-acf-ft-class.php:151
34 | msgid "Close import modal."
35 | msgstr "Fermer la boîte de dialogue de chargement."
36 |
37 | #: includes/mc-acf-ft-class.php:172
38 | msgid "Select a template :"
39 | msgstr "Sélectionnez un modèle :"
40 |
41 | #: includes/mc-acf-ft-class.php:173
42 | msgid "Select a template"
43 | msgstr "Sélectionnez un modèle"
44 |
45 | #: includes/mc-acf-ft-class.php:205
46 | msgid "Uncategorised"
47 | msgstr "Non classé(s)"
48 |
49 | #: includes/mc-acf-ft-class.php:213
50 | msgid "Load"
51 | msgstr "Charger"
52 |
53 | #: includes/mc-acf-ft-class.php:215
54 | msgid "No template found for this flexible"
55 | msgstr "Pas de modèle trouvé pour ce champs flexible."
56 |
57 | #: includes/mc-acf-ft-class.php:238
58 | msgid "Save template"
59 | msgstr "Sauvegarder le modèle"
60 |
61 | #: includes/mc-acf-ft-class.php:242
62 | msgid "Close save modal."
63 | msgstr "Fermer la boîte de dialogue de sauvegarde."
64 |
65 | #: includes/mc-acf-ft-class.php:248
66 | msgid "Select one or more categories :"
67 | msgstr "Sélectionnez une ou plusieurs catégorie(s)"
68 |
69 | #: includes/mc-acf-ft-class.php:249
70 | msgid "Select"
71 | msgstr "Sélection"
72 |
73 | #: includes/mc-acf-ft-class.php:257
74 | msgid "Name the template :"
75 | msgstr "Nommez le modèle :"
76 |
77 | #: includes/mc-acf-ft-class.php:261
78 | msgid "Save"
79 | msgstr "Sauvegarder"
80 |
81 | #: includes/mc-acf-ft-class.php:279 includes/mc-acf-ft-class.php:402
82 | msgid "Ok!"
83 | msgstr ""
84 |
85 | #: includes/mc-acf-ft-class.php:298
86 | msgid "You can't save empty template."
87 | msgstr "Vous ne pouvez pas sauvegarder un modèle vide."
88 |
89 | #: includes/mc-acf-ft-class.php:306
90 | msgid "Template name input not found."
91 | msgstr "Le champs du nom du modèle n'a pas été trouvé."
92 |
93 | #: includes/mc-acf-ft-class.php:314
94 | msgid "Please fill the template name."
95 | msgstr "Saisissez un nom pour ce modèle."
96 |
97 | #: includes/mc-acf-ft-class.php:346
98 | msgid "Error creating post."
99 | msgstr "Erreur lors de la création du modèle."
100 |
101 | #: includes/mc-acf-ft-class.php:370
102 | msgid "Template saved, remember to save the post."
103 | msgstr "Modèle sauvegardé, pensez à enregistrer votre contenu."
104 |
105 | #: includes/mc-acf-ft-class.php:375
106 | msgid "No layouts for this flexible field."
107 | msgstr "Aucun layout trouvé pour ce champs flexible."
108 |
109 | #: includes/mc-acf-ft-class.php:421
110 | msgid "Import template select not found."
111 | msgstr "Le sélecteur de modèle n'a pas été trouvé."
112 |
113 | #: includes/mc-acf-ft-class.php:429
114 | msgid "Please select a template."
115 | msgstr "Sélectionnez un modèle."
116 |
117 | #: includes/mc-acf-ft-class.php:506
118 | msgid "Template imported, remember to save the post."
119 | msgstr "Modèle chargé, pensez à enregistrer votre contenu."
120 |
121 | #: includes/mc-acf-ft-class.php:512
122 | msgid "ACF main class not found."
123 | msgstr "La classe ACF n'a pas été trouvée."
124 |
125 | #: includes/mc-acf-ft-class.php:518
126 | msgid "You can't import empty template."
127 | msgstr "Vous ne pouvez pas charger un modèle vide."
128 |
129 | #: includes/mc-acf-ft-class.php:590
130 | msgid "Save as template :"
131 | msgstr "Sauvegarder le modèle :"
132 |
133 | #: includes/mc-acf-ft-register-cpt.php:14
134 | #: includes/mc-acf-ft-register-cpt.php:53
135 | #: includes/mc-acf-ft-register-cpt.php:54
136 | msgid "ACF Template"
137 | msgstr "Modèle ACF"
138 |
139 | #: includes/mc-acf-ft-register-cpt.php:17
140 | msgid "ACF Templates"
141 | msgstr "Modèles ACF"
142 |
143 | #: includes/mc-acf-ft-register-cpt.php:20
144 | msgid "All ACF Templates"
145 | msgstr "Tous les modèles ACF"
146 |
147 | #: includes/mc-acf-ft-register-cpt.php:28
148 | msgid "ACF Template Archives"
149 | msgstr "Archives des modèles ACF"
150 |
151 | #: includes/mc-acf-ft-register-cpt.php:29
152 | msgid "ACF Template Attributes"
153 | msgstr "Attributs des modèles ACF"
154 |
155 | #: includes/mc-acf-ft-register-cpt.php:30
156 | #: includes/mc-acf-ft-register-cpt.php:91
157 | msgid "Parent Item:"
158 | msgstr "Parent:"
159 |
160 | #: includes/mc-acf-ft-register-cpt.php:32
161 | #: includes/mc-acf-ft-register-cpt.php:93
162 | msgid "Add New Item"
163 | msgstr "Ajouter"
164 |
165 | #: includes/mc-acf-ft-register-cpt.php:33
166 | msgid "Add New"
167 | msgstr "Ajouter"
168 |
169 | #: includes/mc-acf-ft-register-cpt.php:34
170 | msgid "New Item"
171 | msgstr "Nouveau"
172 |
173 | #: includes/mc-acf-ft-register-cpt.php:35
174 | #: includes/mc-acf-ft-register-cpt.php:94
175 | msgid "Edit Item"
176 | msgstr "Modifier"
177 |
178 | #: includes/mc-acf-ft-register-cpt.php:36
179 | #: includes/mc-acf-ft-register-cpt.php:95
180 | msgid "Update Item"
181 | msgstr "Mettre à jour"
182 |
183 | #: includes/mc-acf-ft-register-cpt.php:37
184 | #: includes/mc-acf-ft-register-cpt.php:96
185 | msgid "View Item"
186 | msgstr "Voir"
187 |
188 | #: includes/mc-acf-ft-register-cpt.php:38
189 | msgid "View Items"
190 | msgstr "Voir"
191 |
192 | #: includes/mc-acf-ft-register-cpt.php:39
193 | msgid "Search Item"
194 | msgstr ""
195 |
196 | #: includes/mc-acf-ft-register-cpt.php:40
197 | msgid "Not found"
198 | msgstr ""
199 |
200 | #: includes/mc-acf-ft-register-cpt.php:41
201 | msgid "Not found in Trash"
202 | msgstr ""
203 |
204 | #: includes/mc-acf-ft-register-cpt.php:42
205 | msgid "Featured Image"
206 | msgstr ""
207 |
208 | #: includes/mc-acf-ft-register-cpt.php:43
209 | msgid "Set featured image"
210 | msgstr ""
211 |
212 | #: includes/mc-acf-ft-register-cpt.php:44
213 | msgid "Remove featured image"
214 | msgstr ""
215 |
216 | #: includes/mc-acf-ft-register-cpt.php:45
217 | msgid "Use as featured image"
218 | msgstr ""
219 |
220 | #: includes/mc-acf-ft-register-cpt.php:46
221 | msgid "Insert into item"
222 | msgstr ""
223 |
224 | #: includes/mc-acf-ft-register-cpt.php:47
225 | msgid "Uploaded to this item"
226 | msgstr ""
227 |
228 | #: includes/mc-acf-ft-register-cpt.php:48
229 | #: includes/mc-acf-ft-register-cpt.php:104
230 | msgid "Items list"
231 | msgstr ""
232 |
233 | #: includes/mc-acf-ft-register-cpt.php:49
234 | #: includes/mc-acf-ft-register-cpt.php:105
235 | msgid "Items list navigation"
236 | msgstr ""
237 |
238 | #: includes/mc-acf-ft-register-cpt.php:50
239 | msgid "Filter items list"
240 | msgstr ""
241 |
242 | #: includes/mc-acf-ft-register-cpt.php:86
243 | #: includes/mc-acf-ft-register-cpt.php:88
244 | #: includes/mc-acf-ft-register-cpt.php:89
245 | msgid "Categories"
246 | msgstr "Catégories"
247 |
248 | #: includes/mc-acf-ft-register-cpt.php:87
249 | msgid "Category"
250 | msgstr ""
251 |
252 | #: includes/mc-acf-ft-register-cpt.php:90
253 | msgid "Parent Item"
254 | msgstr ""
255 |
256 | #: includes/mc-acf-ft-register-cpt.php:92
257 | msgid "New Item Name"
258 | msgstr ""
259 |
260 | #: includes/mc-acf-ft-register-cpt.php:97
261 | msgid "Separate items with commas"
262 | msgstr ""
263 |
264 | #: includes/mc-acf-ft-register-cpt.php:98
265 | msgid "Add or remove items"
266 | msgstr ""
267 |
268 | #: includes/mc-acf-ft-register-cpt.php:99
269 | msgid "Choose from the most used"
270 | msgstr ""
271 |
272 | #: includes/mc-acf-ft-register-cpt.php:100
273 | msgid "Popular Items"
274 | msgstr ""
275 |
276 | #: includes/mc-acf-ft-register-cpt.php:101
277 | msgid "Search Items"
278 | msgstr ""
279 |
280 | #: includes/mc-acf-ft-register-cpt.php:102
281 | msgid "Not Found"
282 | msgstr ""
283 |
284 | #: includes/mc-acf-ft-register-cpt.php:103
285 | msgid "No items"
286 | msgstr ""
287 |
288 | #: includes/mc-acf-ft-register-cpt.php:128
289 | msgid "Saved from field :"
290 | msgstr "Sauvegardé depuis le champs :"
291 |
292 | #: includes/mc-acf-ft-register-cpt.php:141
293 | msgid "Unable to get parent flexible"
294 | msgstr "Impossible de récupérer le champs flexible parent."
295 |
296 | #: mc-acf-flexible-template.php:47
297 | msgid ""
298 | "MC ACF Flexible Template plugin needs \"Advanced Custom Fields Pro\" to run. "
299 | "Please download and activate it"
300 | msgstr ""
301 | "L'extension MC ACF Flexible Template requiert \"Advanced Custom Fields Pro\" "
302 | "pour fonctionner. Téléchargez et installez la."
303 |
304 | #~ msgid "All"
305 | #~ msgstr "Tous"
306 |
307 | #~ msgid "Select a category"
308 | #~ msgstr "Sélectionnez une catégorie"
309 |
310 | #~ msgid "Select one or more terms :"
311 | #~ msgstr "Sélectionnez un ou plusieurs termes :"
312 |
313 | #~ msgid "Select a term"
314 | #~ msgstr "Sélectionnez un terme"
315 |
316 | #~ msgid "All Categories"
317 | #~ msgstr "Toutes les catégories"
318 |
319 | #~ msgid "All Items"
320 | #~ msgstr "Tous les modèles"
321 |
322 | #~ msgid "Choose a template :"
323 | #~ msgstr "Sélectionnez un modèle :"
324 |
325 | #~ msgid "Original Flexible"
326 | #~ msgstr "Flexible "
327 |
--------------------------------------------------------------------------------
/assets/js/mc-acf-ft-template.js:
--------------------------------------------------------------------------------
1 | jQuery(document).ready(function($){
2 |
3 | // make sure acf is loaded, it should be, but just in case
4 | if (typeof acf == 'undefined') { return; }
5 |
6 | $('.mc-acf-ft-select2').select2();
7 |
8 | var MC_ACF_Flexible_Template = new acf.Model({
9 |
10 | events: {
11 | 'click button.mc-open': '_open_popup',
12 | 'click button.acf-mc-ft-close': '_close_popup',
13 | 'click .acf-mc-ft-import': '_import_template',
14 | 'click .acf-mc-ft-save': '_save_template',
15 | },
16 |
17 | _open_popup: function( e, $el ) {
18 |
19 | e.preventDefault();
20 | e.stopImmediatePropagation();
21 |
22 | // little fix sometimes select are not initialized
23 | $( '.mc-acf-ft-select2' ).each( function ( i, obj ) {
24 | if ( !$( obj ).hasClass( 'select2-hidden-accessible' ) ) {
25 | $( obj ).select2();
26 | }
27 | });
28 |
29 | // close other popups
30 | $( '.popup' ).hide();
31 | // vars
32 | var popup = $( $el.next( '.popup' ) );
33 |
34 | if ( popup.length ) {
35 | $( popup ).show();
36 | $( popup ).removeClass( '-close' );
37 | $( popup ).addClass( '-open' );
38 | }
39 | },
40 |
41 | _close_popup: function( e, $el ) {
42 |
43 | e.preventDefault();
44 | e.stopImmediatePropagation();
45 | // vars
46 |
47 | var popup = $( $el.parent( '.popup' ) );
48 | if ( popup.length ) {
49 | $( popup ).hide();
50 | $( popup ).removeClass( '-open' );
51 | $( popup ).addClass( '-close' );
52 | }
53 | },
54 | // Import template
55 | _import_template: function( e, $el ) {
56 | e.preventDefault();
57 |
58 | var parentFlex = $el.closest( '.acf-field-flexible-content' );
59 |
60 | // acf flexible ref
61 | var acfFlexible = acf.getField( parentFlex );
62 |
63 | var parentValues = parentFlex.find( '.values' );
64 |
65 | var layouts = parentValues.find( '.layout' );
66 |
67 | var replaceCheckbox = parentFlex.find('input[name=replace_content]');
68 |
69 | var numberLayouts = layouts.length;
70 |
71 | var error_div = parentFlex.find( '.acf-mc-ft-import-error' );
72 | var succes_div = parentFlex.find( '.acf-mc-ft-import-success' );
73 |
74 | $form = $( 'form#post' );
75 |
76 | var template_select = parentFlex.find('.acf-templates-select');
77 | var selectedTemplate = $(template_select).val();
78 |
79 | var data = {
80 | action : 'mc_acf_import_template',
81 | acf_templates : selectedTemplate,
82 | number_layout : numberLayouts
83 | };
84 |
85 | data = acf.prepare_for_ajax( data );
86 |
87 | // set busy
88 | acf.validation.busy = 1;
89 |
90 | // lock form
91 | acf.validation.lockForm( $form );
92 |
93 | var validLayout = false;
94 |
95 | $.post({
96 | url: acf.get( 'ajaxurl' ),
97 | type: 'post',
98 | data: data,
99 | dataType: 'json',
100 | action: 'mc_acf_import_template',
101 | success: function( json ) {
102 |
103 | if( true === json.success ) {
104 |
105 | $( error_div ).hide();
106 |
107 | if( replaceCheckbox.is(':checked') ) {
108 |
109 | layouts.each( function( key, value ) {
110 | acfFlexible.removeLayout( $(value) );
111 | });
112 |
113 | }
114 |
115 | var layoutsHtml = $( json.data.layouts );
116 |
117 | // loop on layouts
118 | $.each( layoutsHtml, function( key, value ) {
119 |
120 | // bail early if validation fails
121 | if( ! acfFlexible.validateAdd() ) {
122 |
123 | validLayout = false;
124 | return false;
125 |
126 | } else {
127 |
128 | // create object for use it later
129 | var newItem = $( value );
130 |
131 | // append to parent
132 | $( parentValues ).append( newItem );
133 | // this action set the field and render correctly tabs, etc.
134 | acf.do_action( 'append', newItem );
135 | // add -collapsed class, if you want all new layouts opened
136 | $( newItem ).addClass( 'just-added bg-green' );
137 | // remove the empty div
138 | $( parentFlex ).find( '.no-value-message' ).hide();
139 |
140 | validLayout = true;
141 |
142 | }
143 |
144 | });
145 |
146 | if ( validLayout ) {
147 | $( succes_div ).text( json.data.message ).show();
148 | }
149 |
150 | setTimeout(function(){
151 | $( succes_div ).text( '' ).hide();
152 | // reset select
153 | $( template_select ).val(null).trigger( 'change' );
154 | // close other popups
155 | $( '.popup' ).hide();
156 | }, 3000);
157 |
158 | } else {
159 | //console.log(json.data.message);
160 | $( succes_div ).hide();
161 | $( error_div ).text( json.data.message ).show();
162 | }
163 |
164 | // unlock so WP can publish form
165 | acf.validation.busy = 0;
166 | acf.validation.unlockForm( $form );
167 | },
168 | error: function( json ) {
169 | console.log( json );
170 | }
171 | });
172 | },
173 |
174 | // Save template
175 | _save_template: function( e, $el ) {
176 | e.preventDefault();
177 |
178 | var parentFlex = $el.closest( '.acf-field-flexible-content' );
179 |
180 | var parentGroupKey = parentFlex.attr( 'data-key' );
181 |
182 | var parentValues = parentFlex.find( '.values' );
183 |
184 | var template_name_input = parentFlex.find( '.acf-mc-ft-template-name' );
185 | var template_name = $( template_name_input ).val();
186 |
187 | var template_terms_select = parentFlex.find( '.acf-templates-terms-select' );
188 | var template_terms = $( template_terms_select ).val();
189 |
190 | var error_div = parentFlex.find( '.acf-mc-ft-save-error' );
191 | var succes_div = parentFlex.find( '.acf-mc-ft-save-success' );
192 |
193 | $form = $( 'form#post' );
194 |
195 | acf.doAction('validation_begin', $form);
196 |
197 | var data = acf.serialize( parentValues );
198 |
199 | // append AJAX action
200 | data.action = 'mc_acf_ft_save_template';
201 | data.mc_acf_template_name = template_name;
202 |
203 | if ( parentGroupKey.length ) {
204 | data.mc_acf_parent_key = parentGroupKey;
205 | }
206 |
207 | if ( template_terms ) {
208 | data.mc_acf_template_terms = template_terms;
209 | }
210 |
211 | data = acf.prepare_for_ajax( data );
212 |
213 | // set busy
214 | acf.validation.busy = 1;
215 |
216 | // lock form
217 | acf.validation.lockForm( $form );
218 |
219 | $.post({
220 | url: acf.get( 'ajaxurl' ),
221 | type: 'post',
222 | data: data,
223 | dataType: 'json',
224 | action: 'mc_acf_ft_save_template',
225 | success: function( json ) {
226 | if ( true === json.success ) {
227 | $( error_div ).hide();
228 | $( succes_div ).text( json.data.message ).show();
229 | setTimeout(function(){
230 | $( succes_div ).text( '' ).hide();
231 | // reset inputs
232 | $( template_name_input ).val( '' );
233 | $( template_terms_select ).val(null).trigger( 'change' );
234 | // close other popups
235 | $( '.popup' ).hide();
236 | }, 3000);
237 | } else {
238 | //console.log(json.data.message);
239 | $( succes_div ).hide();
240 | $( error_div ).text( json.data.message ).show();
241 | }
242 | // unlock so WP can publish form
243 | acf.validation.busy = 0;
244 | acf.validation.unlockForm( $form );
245 | },
246 | error: function( json ) {
247 | console.log('erreur');
248 | }
249 | });
250 | }
251 | });
252 | });
253 |
--------------------------------------------------------------------------------
/includes/class-mc-acf-flexible-template.php:
--------------------------------------------------------------------------------
1 | true,
46 | 'class' => true,
47 | 'value' => true,
48 | 'name' => true,
49 | ];
50 | $tags[ 'select' ] = [
51 | 'style' => true,
52 | 'class' => true,
53 | 'data-placeholder' => true,
54 | 'name' => true,
55 | ];
56 | $tags[ 'option' ] = [
57 | 'value' => true,
58 | ];
59 | }
60 | return $tags;
61 | }
62 |
63 | /*
64 | * mc_ft_acf_update_template
65 | * hooked on acf/save_post
66 | * Update ACF templates data
67 | * @param $post_id INT
68 | * @since 1.0.2
69 | */
70 | public function mc_ft_acf_update_template( $post_id ) {
71 |
72 | if ( wp_is_post_revision( $post_id ) ) {
73 | return;
74 | }
75 |
76 | $post_type = get_post_type( $post_id );
77 |
78 | if ( $post_type !== 'acf_template' ) {
79 | return;
80 | }
81 |
82 | if ( empty( $_POST['acf'] ) ) {
83 | return;
84 | }
85 |
86 | $fields = $_POST['acf'];
87 |
88 |
89 | if ( ! empty( $fields ) && is_array( $fields ) ) {
90 | foreach ( $fields as $key => $field ) {
91 |
92 | if ( ! is_serialized( $field ) ) {
93 | $field = maybe_serialize( $field );
94 | }
95 |
96 | if ( is_string( $field ) ) {
97 | $field = wp_slash( $field );
98 | }
99 |
100 | if ( !empty( $field ) ) {
101 | update_post_meta( $post_id, '_flex_layout_data', $field );
102 | }
103 | }
104 | }
105 | // unset ACF post data because we don't want to add this to post_meta
106 | unset( $_POST['acf'] );
107 | }
108 |
109 | /*
110 | * mc_ft_acf_field_groupos_add_settings
111 | * hooked on acf/render_field_settings
112 | * Add an option to flexible field to turn on/off import and export function by field
113 | * @param $field (array)
114 | * @since 1.0.1
115 | */
116 | public function mc_ft_acf_field_groups_add_settings( $field ) {
117 | // min
118 | acf_render_field_setting( $field, array(
119 | 'label' => __('Save and load templates functionality','mc-acf-ft-template'),
120 | 'instructions' => __('This flexible field should display save/load functionnality ?', 'mc-acf-ft-template'),
121 | 'type' => 'true_false',
122 | 'name' => 'mc_acf_ft_true_false',
123 | 'ui' => 1,
124 | 'default_value' => true,
125 | ) );
126 | }
127 | /*
128 | * mc_ft_add_filter_label
129 | * hooked on acf_get_field_label
130 | * Display the select box for import and export templates
131 | * @param $field (array)
132 | * @return $label (string)
133 | * @since 1.0.1
134 | */
135 | public function mc_ft_add_filter_label( $label, $field ){
136 | global $post, $pagenow, $typenow;
137 |
138 | if ( isset( $field['type'] )
139 | && $field['type'] == 'flexible_content'
140 | && isset( $field['mc_acf_ft_true_false'] ) && $field['mc_acf_ft_true_false']
141 | && ! in_array( $typenow, array( 'acf-field-group', 'attachment', 'acf_template' ) )
142 | && isset( $field['key'] )
143 | && ! empty( $field['key'] ) ) {
144 |
145 | $label .= '';
146 | ob_start();
147 | // Capability for export and import
148 | $import_cap = 'edit_others_pages';
149 | $import_cap = apply_filters( 'mc_ft_import_cap', $import_cap );
150 |
151 | if ( current_user_can( $import_cap ) ) {
152 | $label .= $this->mc_ft_select_display( $field['key'] );
153 | }
154 |
155 | $save_cap = 'edit_others_pages';
156 | $save_cap = apply_filters( 'mc_ft_save_cap', $save_cap );
157 |
158 | if ( current_user_can( $save_cap ) ) {
159 | $label .= $this->mc_ft_save_display( $field['key'] );
160 | }
161 | $label .= ob_get_clean();
162 | $label .= '
';
163 |
164 | }
165 |
166 | return $label;
167 | }
168 |
169 | /*
170 | * mc_ft_select_display
171 | * get acf_template CPT list for the current field group
172 | * $field_key : the current field key group
173 | * @since 1.0.1
174 | */
175 | public function mc_ft_select_display( $field_key ) {
176 |
177 | $templates_tax = get_terms( array(
178 | 'taxonomy' => 'acf_template_tax',
179 | 'hide_empty' => true,
180 | 'orderby' => 'name'
181 | ) );
182 |
183 | ?>
184 |
187 |
188 |
266 | 'acf_template_tax',
278 | 'hide_empty' => false,
279 | 'orderby' => 'name'
280 | ) );
281 |
282 | ?>
283 |
286 |
287 |
311 | true,
324 | 'valid' => 1,
325 | 'errors' => 0,
326 | 'message' => __( 'Ok!', 'mc-acf-ft-template' )
327 | );
328 |
329 | // default error array
330 | $error = array(
331 | 'code' => '',
332 | 'message' => '',
333 | );
334 |
335 | // we can use the acf nonce to verify the request
336 | if ( ! wp_verify_nonce( $_POST['nonce'], 'acf_nonce' ) ) {
337 | $error = -1;
338 | wp_send_json_error( $error );
339 | exit;
340 | }
341 |
342 | // make sure we have ACF data
343 | if ( ! isset( $_POST['acf'] ) || isset( $_POST['acf'] ) && empty( $_POST['acf'] ) ) {
344 | $error['code'] = 0;
345 | $error['message'] = __( 'You can\'t save empty template.', 'mc-acf-ft-template' );
346 | wp_send_json_error( $error );
347 | exit;
348 | }
349 |
350 | // make sure our template name is set
351 | if ( ! isset( $_POST['mc_acf_template_name'] ) ) {
352 | $error['code'] = -1;
353 | $error['message'] = __( 'Template name input not found.', 'mc-acf-ft-template' );
354 | wp_send_json_error( $error );
355 | exit;
356 | }
357 |
358 | // make sure our template name is set and not empty
359 | if ( isset( $_POST['mc_acf_template_name'] ) && empty( $_POST['mc_acf_template_name'] ) ) {
360 | $error['code'] = -2;
361 | $error['message'] = __( 'Please fill the template name.', 'mc-acf-ft-template' );
362 | wp_send_json_error( $error );
363 | exit;
364 | }
365 |
366 | // we have our custom field and acf post data
367 | if ( isset( $_POST['mc_acf_parent_key'] ) && ! empty( $_POST['mc_acf_parent_key'] ) ) {
368 |
369 | $template_name = $_POST['mc_acf_template_name'];
370 |
371 | // check if we have an existing template with that name
372 | $maybe_exist_template = get_page_by_title( $template_name, OBJECT, 'acf_template');
373 |
374 | if ( $maybe_exist_template ) {
375 | $error['code'] = 0;
376 | $error['message'] = __( 'A template already exists with that name. Please enter another name.', 'mc-acf-ft-template' );
377 | wp_send_json_error( $error );
378 | exit;
379 | }
380 |
381 | $parent_key = $_POST['mc_acf_parent_key'];
382 |
383 | $fields = $_POST['acf'][$parent_key];
384 |
385 | if ( ! empty( $fields ) && is_array( $fields ) ) {
386 |
387 | if ( ! is_serialized( $fields ) ) {
388 | $fields = maybe_serialize( $fields );
389 | }
390 |
391 | // if we have some flexibles fields, save them in a CPT
392 | $post_arr = array(
393 | 'post_title' => $template_name,
394 | 'post_content' => '',
395 | 'post_status' => 'publish',
396 | 'post_author' => get_current_user_id(),
397 | 'post_type' => 'acf_template',
398 | );
399 |
400 | $post_id = wp_insert_post( $post_arr );
401 |
402 | if ( is_wp_error( $post_id ) ) {
403 | $error['code'] = -3;
404 | $error['message'] = __( 'Error creating post.', 'mc-acf-ft-template' );
405 | wp_send_json_error( $error );
406 | exit;
407 | } else {
408 |
409 | if ( is_string( $fields ) ) {
410 | $fields = wp_slash( $fields );
411 | }
412 |
413 | if ( ! add_post_meta( $post_id, '_flex_layout_parent', $parent_key, true ) ) {
414 | update_post_meta( $post_id, '_flex_layout_parent', $parent_key );
415 | }
416 |
417 | if ( ! add_post_meta( $post_id, '_flex_layout_data', $fields, true ) ) {
418 | update_post_meta( $post_id, '_flex_layout_data', $fields );
419 | }
420 |
421 | if ( isset( $_POST['mc_acf_template_terms'] ) && ! empty( $_POST['mc_acf_template_terms'] ) ) {
422 | $terms_selected = $_POST['mc_acf_template_terms'];
423 | if( is_array( $terms_selected ) && ! empty( $terms_selected ) ) {
424 | wp_set_post_terms( $post_id, $terms_selected, 'acf_template_tax', true );
425 | }
426 | }
427 |
428 | $json['message'] = __( 'Template saved, remember to save the post.', 'mc-acf-ft-template' );
429 | }
430 |
431 | } else {
432 | $error['code'] = -4;
433 | $error['message'] = __( 'No layouts for this flexible field.', 'mc-acf-ft-template' );
434 | wp_send_json_error( $error );
435 | exit;
436 | }
437 |
438 | }
439 |
440 | wp_send_json_success( $json );
441 |
442 | exit;
443 |
444 | } // end public function mc_acf_ft_save_template
445 |
446 | /*
447 | * Import template
448 | * Ajac function to import flexible template
449 | * @since 1.0.1
450 | */
451 | public function mc_acf_import_template() {
452 |
453 | global $post;
454 |
455 | // Default json return if ok
456 | $json = array(
457 | 'success' => true,
458 | 'valid' => 1,
459 | 'errors' => 0,
460 | 'message' => __( 'Ok!', 'mc-acf-ft-template' ),
461 | );
462 |
463 | // default error array
464 | $error = array(
465 | 'code' => '',
466 | 'message' => '',
467 | );
468 |
469 | // we can use the acf nonce to verify the request
470 | if ( ! wp_verify_nonce( $_POST['nonce'], 'acf_nonce' ) ) {
471 | $error = -1;
472 | wp_send_json_error( $error );
473 | exit;
474 | }
475 |
476 | // make sure our template name is set
477 | if ( ! isset( $_POST['acf_templates'] ) ) {
478 | $error['code'] = -1;
479 | $error['message'] = __( 'Import template select not found.', 'mc-acf-ft-template' );
480 | wp_send_json_error( $error );
481 | exit;
482 | }
483 |
484 | // make sure our template name is set and not empty
485 | if ( isset( $_POST['acf_templates'] ) && empty( $_POST['acf_templates'] ) ) {
486 | $error['code'] = -2;
487 | $error['message'] = __( 'Please select a template.', 'mc-acf-ft-template' );
488 | wp_send_json_error( $error );
489 | exit;
490 | }
491 |
492 | if ( isset( $_POST['acf_templates'] ) && ! empty( $_POST['acf_templates'] ) ) {
493 |
494 | // the CPT (template) selected
495 | $flex_layout_id = $_POST['acf_templates'];
496 | // layouts count in page (.values > .layout)
497 | // we can't get this values using get_row on post_id because maybe user has added layouts BEFORE import
498 | $initial_count = $_POST['number_layout'];
499 |
500 | // the flexible layout meta data saved in the template
501 | $layouts_serialized = get_post_meta( $flex_layout_id, '_flex_layout_data', true );
502 |
503 | $layouts = maybe_unserialize( $layouts_serialized );
504 |
505 | if ( is_array( $layouts ) && ! empty( $layouts ) ) {
506 |
507 | // the original ACF field group from which template was saved
508 | $layout_parent_key = get_post_meta( $flex_layout_id, '_flex_layout_parent', true );
509 |
510 | // get the original field object
511 | // needed in the render_layout function
512 | $parent_object = get_field_object( $layout_parent_key, true, true );
513 |
514 | // acf flexible main class
515 | if ( class_exists('acf_field_flexible_content') ) {
516 | $acf_flex_class = new acf_field_flexible_content();
517 |
518 | /*
519 | * Some loops, here's the point :
520 | * When saving template, I add to post_meta ONLY the serialized values from the flexible content
521 | * (which meen only layouts, and not all the flexible parent group) for the current post.
522 | * I could save ALL the parent group object and simply output it here and avoid some loops
523 | * But flexible content field can be VERY large and complex, which meen a lot of data.
524 | * I prefer rebuild the field object here and put our layouts value in.
525 | */
526 | // we push our saved template values in group parent object
527 | foreach ( $layouts as $i => $value ) {
528 | $parent_object['value'][] = $value;
529 | // add the name according to the group parent key, used in layout input hidden
530 | // used by ACF in render_layout function
531 | $parent_object['name'] = 'acf['.$layout_parent_key.']';
532 | }
533 |
534 | // here we are creating a "fake" layouts array
535 | // based on the group parent object (flexible)
536 | $fake_layouts = array();
537 |
538 | // loop on group parent layouts and push the name, used later by ACF
539 | foreach ( $parent_object['layouts'] as $k => $layout ) {
540 | $fake_layouts[ $layout['name'] ] = $layout;
541 | }
542 |
543 | $item = array();
544 | // loop on parent object values, now contain our templates values
545 |
546 | foreach ( $parent_object['value'] as $i => $value ) {
547 | // check if layout exist in parent group now
548 | if ( array_key_exists( $value['acf_fc_layout'], $fake_layouts ) ) {
549 | // unslash values
550 | $value = wp_unslash($value);
551 |
552 | ob_start();
553 | // render LAYOUT
554 | $acf_flex_class->render_layout( $parent_object, $fake_layouts[ $value['acf_fc_layout'] ],
555 | $initial_count, $value );
556 | $item[] = ob_get_clean();
557 | // increment counter
558 | $initial_count++;
559 |
560 | }
561 | }
562 |
563 | $json['layouts'] = $item;
564 | $json['message'] = __( 'Template imported, remember to save the post.', 'mc-acf-ft-template' );
565 | if ( is_array( $item ) ) {
566 | wp_send_json_success( $json );
567 | }
568 | } else {
569 | $error['code'] = -3;
570 | $error['message'] = __( 'ACF main class not found.', 'mc-acf-ft-template' );
571 | wp_send_json_error( $error );
572 | exit;
573 | }
574 | } else {
575 | $error['code'] = -4;
576 | $error['message'] = __( 'You can\'t import empty template.', 'mc-acf-ft-template' );
577 | wp_send_json_error( $error );
578 | exit;
579 | }
580 | }
581 | }
582 |
583 | /*
584 | * mc_acf_ft_after_title
585 | * Display our custom flexible fields in acf template CPT
586 | * $post : post object
587 | * @since 1.0.1
588 | */
589 | public function mc_acf_ft_after_title( $post ) {
590 | if ( $post->post_type !== 'acf_template' ) {
591 | return;
592 | }
593 |
594 | $flex_layout_id = $post->ID;
595 | // the flexible layout meta data saved in the template
596 | $layouts_serialized = get_post_meta( $flex_layout_id, '_flex_layout_data', true );
597 | $layouts = maybe_unserialize( $layouts_serialized );
598 |
599 | // the original ACF field group from which template was saved
600 | $layout_parent_key = get_post_meta( $flex_layout_id, '_flex_layout_parent', true );
601 |
602 | // get the original field object
603 | // needed in the render_layout function
604 | $parent_object = get_field_object( $layout_parent_key, true, true );
605 |
606 | if ( is_array( $layouts ) && ! empty( $layouts ) ) {
607 | // acf flexible main class
608 | if ( class_exists( 'acf_field_flexible_content' ) ) {
609 | // we push our saved template values in group parent object
610 | foreach ( $layouts as $i => $value ) {
611 |
612 | // unslash values
613 | $value = wp_unslash($value);
614 | $parent_object['value'][] = $value;
615 | // add the name according to the group parent key, used in layout input hidden
616 | // used by ACF in render_layout function
617 | $parent_object['name'] = 'acf['.$layout_parent_key.']';
618 | }
619 | // render field with values
620 | acf_render_fields( $flex_layout_id, array( $parent_object ), $el = 'div', $instruction = 'label' );
621 | }
622 | } else {
623 | // render field without value
624 | acf_render_fields( $flex_layout_id, array( $parent_object ), $el = 'div', $instruction = 'label' );
625 | }
626 | }
627 |
628 | public function enqueue_script() {
629 |
630 | global $post;
631 |
632 | if ( $post &&
633 | isset( $post->ID ) &&
634 | get_post_type( $post->ID ) === 'acf-field-group') {
635 | return;
636 | }
637 |
638 | // the handle should be changed to your own unique handle
639 | $handle = 'mc-acf-ft-template-js';
640 |
641 | $src = MC_ACF_FT . '/assets/js/mc-acf-ft-template.js';
642 | // make this script dependent on acf-input
643 | $depends = array( 'acf-input' );
644 |
645 | $localize = array();
646 | $localize['ft_label'] = __( 'Save as template :', 'mc-acf-ft-template' );
647 | //$localized['ft_save'] = __( "Save this template", 'mc-acf-ft-template' );
648 |
649 | wp_register_script( $handle, $src, $depends );
650 |
651 | wp_enqueue_script( $handle );
652 |
653 | wp_localize_script( $handle, 'mc_acf_ft', $localize );
654 |
655 | // CSS
656 | wp_register_style( 'mc-acf-ft-css', MC_ACF_FT . 'assets/css/mc-acf-ft-css.css' );
657 | wp_enqueue_style( 'mc-acf-ft-css' );
658 | } // end public function enqueue_script
659 |
660 | }
661 |
662 | global $mc_acf_ft;
663 |
664 | if ( ! isset( $mc_acf_ft ) ) {
665 |
666 | $mc_acf_ft = new MC_Acf_Flexible_Template();
667 |
668 | }
669 | }
670 |
--------------------------------------------------------------------------------