From 420d0d8003c7e1a1042f87ae6b9a158387dfc7aa Mon Sep 17 00:00:00 2001 From: Thor Brink Date: Mon, 6 Nov 2023 12:19:40 +0000 Subject: [PATCH] feat: increased isolation of posts from remote api * solves issue with conflicting remote and local post ids * separates creation of types into its own ui * sets a more clear structure for classes/files involved --- .../json/options-api-resources-apis.json | 76 ++ .../json/options-theme-custom-post-type.json | 48 - library/AcfFields/json/resource-fields.json | 1153 ++++++++++++++++ .../php/options-api-resources-apis.php | 79 ++ .../php/options-theme-custom-post-type.php | 64 +- library/AcfFields/php/resource-fields.php | 1160 +++++++++++++++++ library/App.php | 17 +- library/Bootstrap.php | 2 + library/Content/CustomPostType.php | 10 +- library/Content/CustomPostTypesFromApi.php | 219 ---- library/Content/CustomTaxonomiesFromApi.php | 82 -- library/Content/CustomTaxonomyFromApi.php | 110 -- .../PostType/PostTypeQueriesModifier.php | 293 +++++ .../PostType/PostTypeRegistrar.php | 178 +++ .../PostType/PostTypeResourceRequest.php} | 114 +- .../QueriesModifierInterface.php | 9 + .../ResourceFromApi/ResourcePostType.php | 220 ++++ .../ResourceFromApi/ResourceRegistry.php | 276 ++++ .../ResourceRegistryInterface.php | 12 + .../ResourceRequestInterface.php | 10 + .../Taxonomy/TaxonomyQueriesModifier.php | 166 +++ .../Taxonomy/TaxonomyRegistrar.php | 120 ++ .../Taxonomy/TaxonomyResourceRequest.php | 141 ++ .../TypeRegistrarInterface.php | 11 + .../ContentType/ContentTypeComplex.Test.php | 6 +- .../ContentType/School/SchoolDataPreparer.php | 99 +- .../Controller/SchoolArchiveContentType.php | 4 +- library/Helper/WP.Test.php | 34 + views/v3/content-type-school.blade.php | 10 +- 29 files changed, 4058 insertions(+), 665 deletions(-) create mode 100644 library/AcfFields/json/options-api-resources-apis.json create mode 100644 library/AcfFields/json/resource-fields.json create mode 100644 library/AcfFields/php/options-api-resources-apis.php create mode 100644 library/AcfFields/php/resource-fields.php delete mode 100644 library/Content/CustomPostTypesFromApi.php delete mode 100644 library/Content/CustomTaxonomiesFromApi.php delete mode 100644 library/Content/CustomTaxonomyFromApi.php create mode 100644 library/Content/ResourceFromApi/PostType/PostTypeQueriesModifier.php create mode 100644 library/Content/ResourceFromApi/PostType/PostTypeRegistrar.php rename library/Content/{CustomPostTypeFromApi.php => ResourceFromApi/PostType/PostTypeResourceRequest.php} (58%) create mode 100644 library/Content/ResourceFromApi/QueriesModifierInterface.php create mode 100644 library/Content/ResourceFromApi/ResourcePostType.php create mode 100644 library/Content/ResourceFromApi/ResourceRegistry.php create mode 100644 library/Content/ResourceFromApi/ResourceRegistryInterface.php create mode 100644 library/Content/ResourceFromApi/ResourceRequestInterface.php create mode 100644 library/Content/ResourceFromApi/Taxonomy/TaxonomyQueriesModifier.php create mode 100644 library/Content/ResourceFromApi/Taxonomy/TaxonomyRegistrar.php create mode 100644 library/Content/ResourceFromApi/Taxonomy/TaxonomyResourceRequest.php create mode 100644 library/Content/ResourceFromApi/TypeRegistrarInterface.php create mode 100644 library/Helper/WP.Test.php diff --git a/library/AcfFields/json/options-api-resources-apis.json b/library/AcfFields/json/options-api-resources-apis.json new file mode 100644 index 000000000..efd1fc4f7 --- /dev/null +++ b/library/AcfFields/json/options-api-resources-apis.json @@ -0,0 +1,76 @@ +[{ + "key": "group_653a1673dc501", + "title": "Api Resources - Api:s", + "fields": [ + { + "key": "field_653a16743bbcd", + "label": "Api:s", + "name": "api_resources_apis", + "aria-label": "", + "type": "repeater", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "acfe_repeater_stylised_button": 1, + "layout": "block", + "pagination": 0, + "min": 0, + "max": 0, + "collapsed": "", + "button_label": "Add Row", + "rows_per_page": 20, + "sub_fields": [ + { + "key": "field_653a16a23bbce", + "label": "Url", + "name": "url", + "aria-label": "", + "type": "url", + "instructions": "", + "required": 1, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "placeholder": "https:\/\/dummy.api\/wp-json\/wp\/v2", + "parent_repeater": "field_653a16743bbcd" + } + ] + } + ], + "location": [ + [ + { + "param": "options_page", + "operator": "==", + "value": "api-resource-apis" + } + ] + ], + "menu_order": 0, + "position": "normal", + "style": "default", + "label_placement": "left", + "instruction_placement": "label", + "hide_on_screen": "", + "active": true, + "description": "", + "show_in_rest": 0, + "acfe_display_title": "", + "acfe_autosync": [ + "php", + "json" + ], + "acfe_form": 0, + "acfe_meta": "", + "acfe_note": "" +}] + \ No newline at end of file diff --git a/library/AcfFields/json/options-theme-custom-post-type.json b/library/AcfFields/json/options-theme-custom-post-type.json index 8fa8808eb..b8394cfdf 100644 --- a/library/AcfFields/json/options-theme-custom-post-type.json +++ b/library/AcfFields/json/options-theme-custom-post-type.json @@ -155,24 +155,6 @@ "search_placeholder": "", "parent_repeater": "field_56b347f3ffb6c" }, - { - "key": "field_652cf6c8921b0", - "label": "API Source URL", - "name": "api_source_url", - "aria-label": "", - "type": "url", - "instructions": "API Source for the post type. If this is supplied and responds with a WordPress REST API endpoint for a post type collection; the posts for this post type will be served from the supplied endpoint.", - "required": 0, - "conditional_logic": 0, - "wrapper": { - "width": "", - "class": "", - "id": "" - }, - "default_value": "", - "placeholder": "E.g. ...\/wp-json\/wp\/v2\/pre-school", - "parent_repeater": "field_56b347f3ffb6c" - }, { "key": "field_56b361b25defd", "label": "Public?", @@ -278,36 +260,6 @@ "ui_off_text": "", "parent_repeater": "field_56b347f3ffb6c" }, - { - "key": "field_652e6004ffdab", - "label": "Parent post types", - "name": "parent_post_types", - "aria-label": "", - "type": "posttype_select", - "instructions": "Post types that will be used as a parent post type for this post type. This will mainly affects the post type permalinks by prefixing the url with the parent post types post url.", - "required": 0, - "conditional_logic": [ - [ - { - "field": "field_56b364336050a", - "operator": "==", - "value": "1" - } - ] - ], - "wrapper": { - "width": "", - "class": "", - "id": "" - }, - "default_value": "", - "allow_null": 1, - "multiple": 1, - "placeholder": "", - "disabled": 0, - "readonly": 0, - "parent_repeater": "field_56b347f3ffb6c" - }, { "key": "field_5805d63cdcbf4", "label": "Navigation", diff --git a/library/AcfFields/json/resource-fields.json b/library/AcfFields/json/resource-fields.json new file mode 100644 index 000000000..47b6ccbb4 --- /dev/null +++ b/library/AcfFields/json/resource-fields.json @@ -0,0 +1,1153 @@ +[{ + "key": "group_653a509450198", + "title": "Api Resource fields", + "fields": [ + { + "key": "field_653a5094a6168", + "label": "Type", + "name": "type", + "aria-label": "", + "type": "select", + "instructions": "", + "required": 1, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "choices": { + "postType": "Post Type", + "taxonomy": "Taxonomy", + "attachment": "Attachment" + }, + "default_value": false, + "return_format": "value", + "multiple": 0, + "allow_custom": 0, + "search_placeholder": "", + "allow_null": 0, + "ui": 1, + "ajax": 0, + "placeholder": "" + }, + { + "key": "field_653a52d126e03", + "label": "Post Type Source", + "name": "post_type_source", + "aria-label": "", + "type": "select", + "instructions": "", + "required": 1, + "conditional_logic": [ + [ + { + "field": "field_653a5094a6168", + "operator": "==", + "value": "postType" + } + ], + [ + { + "field": "field_653a5094a6168", + "operator": "==", + "value": "attachment" + } + ] + ], + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "choices": { + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/posts": "post: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/posts", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/pages": "page: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/pages", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/media": "attachment: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/media", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/menu-items": "nav_menu_item: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/menu-items", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/blocks": "wp_block: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/blocks", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/templates": "wp_template: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/templates", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/template-parts": "wp_template_part: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/template-parts", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/navigation": "wp_navigation: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/navigation", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/pre-school": "pre-school: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/pre-school", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/elementary-school": "elementary-school: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/elementary-school", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/person": "person: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/person", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/media": "attachment: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/media", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/event": "event: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/event", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/location": "location: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/location", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/organizer": "organizer: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/organizer", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/sponsor": "sponsor: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/sponsor", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/membership-card": "membership-card: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/membership-card", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/guide": "guide: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/guide", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/interactive_guide": "interactive_guide: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/interactive_guide" + }, + "default_value": false, + "return_format": "value", + "multiple": 0, + "allow_custom": 0, + "search_placeholder": "", + "allow_null": 0, + "ui": 1, + "ajax": 1, + "placeholder": "" + }, + { + "key": "field_653a539bb2fc9", + "label": "Taxonomy Source", + "name": "taxonomy_source", + "aria-label": "", + "type": "select", + "instructions": "", + "required": 1, + "conditional_logic": [ + [ + { + "field": "field_653a5094a6168", + "operator": "==", + "value": "taxonomy" + } + ] + ], + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "choices": { + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/categories": "category: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/categories", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/tags": "post_tag: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/tags", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/menus": "nav_menu: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/menus", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/area": "area: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/area", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/usp": "usp: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/usp", + "https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/grade": "grade: https:\/\/skolor.helsingborg.io\/wp-json\/wp\/v2\/grade", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/categories": "category: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/categories", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/tags": "post_tag: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/tags", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/user_groups": "user_groups: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/user_groups", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/event_categories": "event_categories: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/event_categories", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/event_tags": "event_tags: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/event_tags", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/location_categories": "location_categories: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/location_categories", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/guidegroup": "guidegroup: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/guidegroup", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/navigation": "navigation: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/navigation", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/guidetype": "guidetype: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/guidetype", + "https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/property": "property: https:\/\/api.helsingborg.se\/event\/json\/wp\/v2\/property" + }, + "default_value": false, + "return_format": "value", + "multiple": 0, + "allow_custom": 0, + "search_placeholder": "", + "allow_null": 0, + "ui": 1, + "ajax": 1, + "placeholder": "" + }, + { + "key": "field_653b48052dc15", + "label": "Post Type Arguments", + "name": "post_type_arguments", + "aria-label": "", + "type": "group", + "instructions": "", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_653a5094a6168", + "operator": "==", + "value": "postType" + }, + { + "field": "field_653a52d126e03", + "operator": "!=empty" + } + ] + ], + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "layout": "block", + "acfe_seamless_style": 0, + "acfe_group_modal": 0, + "sub_fields": [ + { + "key": "field_601b9c6128f07", + "label": "Post Type Key", + "name": "post_type_key", + "aria-label": "", + "type": "text", + "instructions": "The key of the post type. Max. 20 characters, cannot contain capital letters or spaces.", + "required": true, + "conditional_logic": false, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "maxlength": "", + "placeholder": "", + "prepend": "", + "append": "" + }, + { + "key": "field_65420ddf4476f", + "label": "Label (plural)", + "name": "label", + "aria-label": "", + "type": "text", + "instructions": "", + "required": 1, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "maxlength": "", + "placeholder": "", + "prepend": "", + "append": "" + }, + { + "key": "field_65420e0644770", + "label": "Label (singular)", + "name": "labels_singular_name", + "aria-label": "", + "type": "text", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "maxlength": "", + "placeholder": "", + "prepend": "", + "append": "" + }, + { + "key": "field_601b9c6128f08", + "label": "Description", + "name": "description", + "aria-label": "", + "type": "textarea", + "instructions": "A short descriptive summary of what the post type is.", + "required": false, + "conditional_logic": false, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "new_lines": "", + "maxlength": "", + "placeholder": "", + "rows": "" + }, + { + "key": "field_601b9c6128f09", + "label": "Public", + "name": "public", + "aria-label": "", + "type": "true_false", + "instructions": "Whether the post type should be publicly queryable.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_601b9c6128f19", + "label": "Hierarchical", + "name": "hierarchical", + "aria-label": "", + "type": "true_false", + "instructions": "Whether the post type is hierarchical. Allows Parent to be specified.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_601b9c6128f10", + "label": "Show UI", + "name": "show_ui", + "aria-label": "", + "type": "true_false", + "instructions": "Whether to generate a default UI for managing this post type.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_601b9c6128f11", + "label": "Has Archive", + "name": "has_archive", + "aria-label": "", + "type": "true_false", + "instructions": "Enables post type archives.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_601b9c6128f12", + "label": "Exclude From Search", + "name": "exclude_from_search", + "aria-label": "", + "type": "true_false", + "instructions": "Whether to exclude posts with this post type from front end search results.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_601b9c6128f13", + "label": "Publicly Queryable", + "name": "publicly_queryable", + "aria-label": "", + "type": "true_false", + "instructions": "Whether queries can be performed on the front end as part of parse_request().", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_601b9c6128f14", + "label": "Show In Nav Menus", + "name": "show_in_nav_menus", + "aria-label": "", + "type": "true_false", + "instructions": "Whether post_type is available for selection in navigation menus.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_601b9c6128f15", + "label": "Show In Menu", + "name": "show_in_menu", + "aria-label": "", + "type": "true_false", + "instructions": "Where to show the post type in the admin menu. show_ui must be true.", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_601b9c6128f10", + "operator": "==", + "value": "1" + } + ] + ], + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_601b9c6128f16", + "label": "Show In Admin Bar", + "name": "show_in_admin_bar", + "aria-label": "", + "type": "true_false", + "instructions": "Where to show the post type in the admin bar. show_in_menu must be true.", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_601b9c6128f15", + "operator": "==", + "value": "1" + } + ] + ], + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_601b9c6128f21", + "label": "Rewrite", + "name": "rewrite", + "aria-label": "", + "type": "true_false", + "instructions": "Triggers the handling of rewrites for this post type.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_601b9c6128f17", + "label": "Menu Position", + "name": "menu_position", + "aria-label": "", + "type": "number", + "instructions": "The position in the menu order the post type should appear. show_in_menu must be true.", + "required": false, + "conditional_logic": [ + [ + { + "field": "field_601b9c6128f15", + "operator": "==", + "value": "1" + } + ] + ], + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "min": "", + "max": "", + "step": "", + "placeholder": "", + "prepend": "", + "append": "" + }, + { + "key": "field_601b9c6128f18", + "label": "Capabilities", + "name": "capabilities", + "aria-label": "", + "type": "select", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "choices": [], + "default_value": [], + "return_format": "value", + "multiple": 1, + "allow_custom": 1, + "placeholder": "eg. \"manage_options\"...", + "allow_null": 0, + "ui": 1, + "ajax": 0 + }, + { + "key": "field_6544a42c139a9", + "label": "Parent post types", + "name": "parent_post_types", + "aria-label": "", + "type": "posttype_select", + "instructions": "Parent post types are used to determine the permalink and the rewrite rules for this post type. Setting parent post types will affect the rewrite slug by prepending it with the parent post types slug.", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_601b9c6128f19", + "operator": "==", + "value": "1" + } + ] + ], + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "allow_null": 1, + "multiple": 1, + "placeholder": "", + "disabled": 0, + "readonly": 0 + }, + { + "key": "field_653b5d117edbf", + "label": "Rewrite options", + "name": "rewrite_options", + "aria-label": "", + "type": "group", + "instructions": "Triggers the handling of rewrites for this post type.", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_601b9c6128f21", + "operator": "==", + "value": "1" + } + ] + ], + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "layout": "block", + "acfe_seamless_style": 0, + "acfe_group_modal": 0, + "sub_fields": [ + { + "key": "field_653b5d227edc0", + "label": "Slug", + "name": "slug", + "aria-label": "", + "type": "text", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "50", + "class": "", + "id": "" + }, + "default_value": "", + "maxlength": "", + "placeholder": "", + "prepend": "", + "append": "" + }, + { + "key": "field_653b5d627edc1", + "label": "With front", + "name": "with_front", + "aria-label": "", + "type": "true_false", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "25", + "class": "", + "id": "" + }, + "message": "", + "default_value": 1, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_653b5d727edc2", + "label": "Feeds", + "name": "feeds", + "aria-label": "", + "type": "true_false", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "25", + "class": "", + "id": "" + }, + "message": "", + "default_value": 1, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + } + ] + }, + { + "key": "field_601b9c6128f22", + "label": "Query Var", + "name": "query_var", + "aria-label": "", + "type": "text", + "instructions": "Sets the query_var key for this post type.", + "required": false, + "conditional_logic": false, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "maxlength": "", + "placeholder": "", + "prepend": "", + "append": "" + } + ] + }, + { + "key": "field_6541eda1a37ac", + "label": "Taxonomy Arguments", + "name": "taxonomy_arguments", + "aria-label": "", + "type": "group", + "instructions": "", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_653a5094a6168", + "operator": "==", + "value": "taxonomy" + }, + { + "field": "field_653a539bb2fc9", + "operator": "!=empty" + } + ] + ], + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "layout": "block", + "acfe_seamless_style": 0, + "acfe_group_modal": 0, + "sub_fields": [ + { + "key": "field_6541eda2a37ad", + "label": "Taxonomy key", + "name": "taxonomy_key", + "aria-label": "", + "type": "text", + "instructions": "The key of the post type. Max. 32 characters, cannot contain capital letters or spaces.", + "required": 1, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "maxlength": "", + "placeholder": "", + "prepend": "", + "append": "" + }, + { + "key": "field_654253463faf6", + "label": "Label (Plural)", + "name": "labels_name", + "aria-label": "", + "type": "text", + "instructions": "The key of the post type. Max. 32 characters, cannot contain capital letters or spaces.", + "required": 1, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "maxlength": "", + "placeholder": "", + "prepend": "", + "append": "" + }, + { + "key": "field_654253693faf7", + "label": "Label (Singular)", + "name": "labels_singular_name", + "aria-label": "", + "type": "text", + "instructions": "The key of the post type. Max. 32 characters, cannot contain capital letters or spaces.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "maxlength": "", + "placeholder": "", + "prepend": "", + "append": "" + }, + { + "key": "field_6541ee02a37c0", + "label": "Object Type", + "name": "object_type", + "aria-label": "", + "type": "posttype_select", + "instructions": "Post Types to which this taxonomy should be connected to.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "allow_null": 1, + "multiple": 1, + "placeholder": "", + "disabled": 0, + "readonly": 0 + }, + { + "key": "field_6541eda2a37ae", + "label": "Description", + "name": "description", + "aria-label": "", + "type": "textarea", + "instructions": "A short descriptive summary of what the post type is.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "acfe_textarea_code": 0, + "maxlength": "", + "rows": "", + "placeholder": "", + "new_lines": "" + }, + { + "key": "field_6541eda2a37af", + "label": "Public", + "name": "public", + "aria-label": "", + "type": "true_false", + "instructions": "Whether the post type should be publicly queryable.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_6541eda2a37b0", + "label": "Hierarchical", + "name": "hierarchical", + "aria-label": "", + "type": "true_false", + "instructions": "Whether the post type is hierarchical. Allows Parent to be specified.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_6541eda2a37b1", + "label": "Show UI", + "name": "show_ui", + "aria-label": "", + "type": "true_false", + "instructions": "Whether to generate a default UI for managing this post type.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_6541ee8c94dac", + "label": "Show Admin Column", + "name": "show_admin_column", + "aria-label": "", + "type": "true_false", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_6541eda2a37b4", + "label": "Publicly Queryable", + "name": "publicly_queryable", + "aria-label": "", + "type": "true_false", + "instructions": "Whether queries can be performed on the front end as part of parse_request().", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_6541eda2a37b5", + "label": "Show In Nav Menus", + "name": "show_in_nav_menus", + "aria-label": "", + "type": "true_false", + "instructions": "Whether post_type is available for selection in navigation menus.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_6541eda2a37b6", + "label": "Show In Menu", + "name": "show_in_menu", + "aria-label": "", + "type": "true_false", + "instructions": "Where to show the post type in the admin menu. show_ui must be true.", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_6541eda2a37b1", + "operator": "==", + "value": "1" + } + ] + ], + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_6541eda2a37b7", + "label": "Show In Admin Bar", + "name": "show_in_admin_bar", + "aria-label": "", + "type": "true_false", + "instructions": "Where to show the post type in the admin bar. show_in_menu must be true.", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_6541eda2a37b6", + "operator": "==", + "value": "1" + } + ] + ], + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_6541eda2a37b8", + "label": "Rewrite", + "name": "rewrite", + "aria-label": "", + "type": "true_false", + "instructions": "Triggers the handling of rewrites for this post type.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "20", + "class": "", + "id": "" + }, + "message": "", + "default_value": 0, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_6541eda2a37ba", + "label": "Capabilities", + "name": "capabilities", + "aria-label": "", + "type": "select", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "choices": [], + "default_value": [], + "return_format": "value", + "multiple": 1, + "allow_custom": 1, + "placeholder": "eg. \"manage_options\"...", + "allow_null": 0, + "ui": 1, + "ajax": 0 + }, + { + "key": "field_6541eda2a37bb", + "label": "Rewrite options", + "name": "rewrite_options", + "aria-label": "", + "type": "group", + "instructions": "Triggers the handling of rewrites for this post type.", + "required": 0, + "conditional_logic": [ + [ + { + "field": "field_6541eda2a37b8", + "operator": "==", + "value": "1" + } + ] + ], + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "layout": "block", + "acfe_seamless_style": 0, + "acfe_group_modal": 0, + "sub_fields": [ + { + "key": "field_6541eda2a37bc", + "label": "Slug", + "name": "slug", + "aria-label": "", + "type": "text", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "50", + "class": "", + "id": "" + }, + "default_value": "", + "maxlength": "", + "placeholder": "", + "prepend": "", + "append": "" + }, + { + "key": "field_6541eda2a37bd", + "label": "With front", + "name": "with_front", + "aria-label": "", + "type": "true_false", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "25", + "class": "", + "id": "" + }, + "message": "", + "default_value": 1, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + }, + { + "key": "field_6541eda2a37be", + "label": "Feeds", + "name": "feeds", + "aria-label": "", + "type": "true_false", + "instructions": "", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "25", + "class": "", + "id": "" + }, + "message": "", + "default_value": 1, + "ui_on_text": "", + "ui_off_text": "", + "ui": 1 + } + ] + }, + { + "key": "field_6541eda2a37bf", + "label": "Query Var", + "name": "query_var", + "aria-label": "", + "type": "text", + "instructions": "Sets the query_var key for this post type.", + "required": 0, + "conditional_logic": 0, + "wrapper": { + "width": "", + "class": "", + "id": "" + }, + "default_value": "", + "maxlength": "", + "placeholder": "", + "prepend": "", + "append": "" + } + ] + } + ], + "location": [ + [ + { + "param": "post_type", + "operator": "==", + "value": "api-resource" + } + ] + ], + "menu_order": 0, + "position": "acf_after_title", + "style": "default", + "label_placement": "left", + "instruction_placement": "label", + "hide_on_screen": "", + "active": true, + "description": "", + "show_in_rest": 0, + "acfe_display_title": "", + "acfe_autosync": [ + "php", + "json" + ], + "acfe_form": 0, + "acfe_meta": "", + "acfe_note": "" +}] + \ No newline at end of file diff --git a/library/AcfFields/php/options-api-resources-apis.php b/library/AcfFields/php/options-api-resources-apis.php new file mode 100644 index 000000000..32aeeb715 --- /dev/null +++ b/library/AcfFields/php/options-api-resources-apis.php @@ -0,0 +1,79 @@ + 'group_653a1673dc501', + 'title' => __('Api Resources - Api:s', 'municipio'), + 'fields' => array( + 0 => array( + 'key' => 'field_653a16743bbcd', + 'label' => __('Api:s', 'municipio'), + 'name' => 'api_resources_apis', + 'aria-label' => '', + 'type' => 'repeater', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'acfe_repeater_stylised_button' => 1, + 'layout' => 'block', + 'pagination' => 0, + 'min' => 0, + 'max' => 0, + 'collapsed' => '', + 'button_label' => __('Add Row', 'municipio'), + 'rows_per_page' => 20, + 'sub_fields' => array( + 0 => array( + 'key' => 'field_653a16a23bbce', + 'label' => __('Url', 'municipio'), + 'name' => 'url', + 'aria-label' => '', + 'type' => 'url', + 'instructions' => '', + 'required' => 1, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'placeholder' => __('https://dummy.api/wp-json/wp/v2', 'municipio'), + 'parent_repeater' => 'field_653a16743bbcd', + ), + ), + ), + ), + 'location' => array( + 0 => array( + 0 => array( + 'param' => 'options_page', + 'operator' => '==', + 'value' => 'api-resource-apis', + ), + ), + ), + 'menu_order' => 0, + 'position' => 'normal', + 'style' => 'default', + 'label_placement' => 'left', + 'instruction_placement' => 'label', + 'hide_on_screen' => '', + 'active' => true, + 'description' => '', + 'show_in_rest' => 0, + 'acfe_display_title' => '', + 'acfe_autosync' => array( + 0 => 'php', + 1 => 'json', + ), + 'acfe_form' => 0, + 'acfe_meta' => '', + 'acfe_note' => '', +)); + } \ No newline at end of file diff --git a/library/AcfFields/php/options-theme-custom-post-type.php b/library/AcfFields/php/options-theme-custom-post-type.php index 41486fd97..0c8c667ff 100644 --- a/library/AcfFields/php/options-theme-custom-post-type.php +++ b/library/AcfFields/php/options-theme-custom-post-type.php @@ -159,24 +159,6 @@ 'parent_repeater' => 'field_56b347f3ffb6c', ), 5 => array( - 'key' => 'field_652cf6c8921b0', - 'label' => __('API Source URL', 'municipio'), - 'name' => 'api_source_url', - 'aria-label' => '', - 'type' => 'url', - 'instructions' => __('API Source for the post type. If this is supplied and responds with a WordPress REST API endpoint for a post type collection; the posts for this post type will be served from the supplied endpoint.', 'municipio'), - 'required' => 0, - 'conditional_logic' => 0, - 'wrapper' => array( - 'width' => '', - 'class' => '', - 'id' => '', - ), - 'default_value' => '', - 'placeholder' => __('E.g. .../wp-json/wp/v2/pre-school', 'municipio'), - 'parent_repeater' => 'field_56b347f3ffb6c', - ), - 6 => array( 'key' => 'field_56b361b25defd', 'label' => __('Public?', 'municipio'), 'name' => 'public', @@ -197,7 +179,7 @@ 'ui_off_text' => '', 'parent_repeater' => 'field_56b347f3ffb6c', ), - 7 => array( + 6 => array( 'key' => 'field_56b362255defe', 'label' => __('Exclude from search?', 'municipio'), 'name' => 'exclude_from_search', @@ -218,7 +200,7 @@ 'ui_off_text' => '', 'parent_repeater' => 'field_56b347f3ffb6c', ), - 8 => array( + 7 => array( 'key' => 'field_56b3629c5deff', 'label' => __('Avabile in nav menus?', 'municipio'), 'name' => 'show_in_nav_menus', @@ -239,7 +221,7 @@ 'ui_off_text' => '', 'parent_repeater' => 'field_56b347f3ffb6c', ), - 9 => array( + 8 => array( 'key' => 'field_56b364336050a', 'label' => __('Hierarchical', 'municipio'), 'name' => 'hierarchical', @@ -260,7 +242,7 @@ 'ui_off_text' => '', 'parent_repeater' => 'field_56b347f3ffb6c', ), - 10 => array( + 9 => array( 'key' => 'field_64fef9ff25f70', 'label' => __('Place under pages menu?', 'municipio'), 'name' => 'place_under_pages_menu', @@ -281,37 +263,7 @@ 'ui_off_text' => '', 'parent_repeater' => 'field_56b347f3ffb6c', ), - 11 => array( - 'key' => 'field_652e6004ffdab', - 'label' => __('Parent post types', 'municipio'), - 'name' => 'parent_post_types', - 'aria-label' => '', - 'type' => 'posttype_select', - 'instructions' => __('Post types that will be used as a parent post type for this post type. This will mainly affects the post type permalinks by prefixing the url with the parent post types post url.', 'municipio'), - 'required' => 0, - 'conditional_logic' => array( - 0 => array( - 0 => array( - 'field' => 'field_56b364336050a', - 'operator' => '==', - 'value' => '1', - ), - ), - ), - 'wrapper' => array( - 'width' => '', - 'class' => '', - 'id' => '', - ), - 'default_value' => '', - 'allow_null' => 1, - 'multiple' => 1, - 'placeholder' => '', - 'disabled' => 0, - 'readonly' => 0, - 'parent_repeater' => 'field_56b347f3ffb6c', - ), - 12 => array( + 10 => array( 'key' => 'field_5805d63cdcbf4', 'label' => __('Navigation', 'municipio'), 'name' => 'show_posts_in_sidebar_menu', @@ -340,7 +292,7 @@ 'ui_off_text' => '', 'parent_repeater' => 'field_56b347f3ffb6c', ), - 13 => array( + 11 => array( 'key' => 'field_56b364a391788', 'label' => __('Post type functions', 'municipio'), 'name' => 'supports', @@ -382,7 +334,7 @@ 'custom_choice_button_text' => 'Add new choice', 'parent_repeater' => 'field_56b347f3ffb6c', ), - 14 => array( + 12 => array( 'key' => 'field_633d67ea3f62c', 'label' => __('Display age notification on posts', 'municipio'), 'name' => 'display_age_notification_on_posts', @@ -403,7 +355,7 @@ 'ui' => 0, 'parent_repeater' => 'field_56b347f3ffb6c', ), - 15 => array( + 13 => array( 'key' => 'field_633d68aec93bb', 'label' => __('Display the notice after this many days', 'municipio'), 'name' => 'post_age_days', diff --git a/library/AcfFields/php/resource-fields.php b/library/AcfFields/php/resource-fields.php new file mode 100644 index 000000000..2a3c10eee --- /dev/null +++ b/library/AcfFields/php/resource-fields.php @@ -0,0 +1,1160 @@ + 'group_653a509450198', + 'title' => __('Api Resource fields', 'municipio'), + 'fields' => array( + 0 => array( + 'key' => 'field_653a5094a6168', + 'label' => __('Type', 'municipio'), + 'name' => 'type', + 'aria-label' => '', + 'type' => 'select', + 'instructions' => '', + 'required' => 1, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'choices' => array( + 'postType' => __('Post Type', 'municipio'), + 'taxonomy' => __('Taxonomy', 'municipio'), + 'attachment' => __('Attachment', 'municipio'), + ), + 'default_value' => false, + 'return_format' => 'value', + 'multiple' => 0, + 'allow_custom' => 0, + 'search_placeholder' => '', + 'allow_null' => 0, + 'ui' => 1, + 'ajax' => 0, + 'placeholder' => '', + ), + 1 => array( + 'key' => 'field_653a52d126e03', + 'label' => __('Post Type Source', 'municipio'), + 'name' => 'post_type_source', + 'aria-label' => '', + 'type' => 'select', + 'instructions' => '', + 'required' => 1, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_653a5094a6168', + 'operator' => '==', + 'value' => 'postType', + ), + ), + 1 => array( + 0 => array( + 'field' => 'field_653a5094a6168', + 'operator' => '==', + 'value' => 'attachment', + ), + ), + ), + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'choices' => array( + 'https://skolor.helsingborg.io/wp-json/wp/v2/posts' => __('post: https://skolor.helsingborg.io/wp-json/wp/v2/posts', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/pages' => __('page: https://skolor.helsingborg.io/wp-json/wp/v2/pages', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/media' => __('attachment: https://skolor.helsingborg.io/wp-json/wp/v2/media', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/menu-items' => __('nav_menu_item: https://skolor.helsingborg.io/wp-json/wp/v2/menu-items', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/blocks' => __('wp_block: https://skolor.helsingborg.io/wp-json/wp/v2/blocks', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/templates' => __('wp_template: https://skolor.helsingborg.io/wp-json/wp/v2/templates', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/template-parts' => __('wp_template_part: https://skolor.helsingborg.io/wp-json/wp/v2/template-parts', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/navigation' => __('wp_navigation: https://skolor.helsingborg.io/wp-json/wp/v2/navigation', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/pre-school' => __('pre-school: https://skolor.helsingborg.io/wp-json/wp/v2/pre-school', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/elementary-school' => __('elementary-school: https://skolor.helsingborg.io/wp-json/wp/v2/elementary-school', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/person' => __('person: https://skolor.helsingborg.io/wp-json/wp/v2/person', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/media' => __('attachment: https://api.helsingborg.se/event/json/wp/v2/media', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/event' => __('event: https://api.helsingborg.se/event/json/wp/v2/event', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/location' => __('location: https://api.helsingborg.se/event/json/wp/v2/location', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/organizer' => __('organizer: https://api.helsingborg.se/event/json/wp/v2/organizer', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/sponsor' => __('sponsor: https://api.helsingborg.se/event/json/wp/v2/sponsor', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/membership-card' => __('membership-card: https://api.helsingborg.se/event/json/wp/v2/membership-card', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/guide' => __('guide: https://api.helsingborg.se/event/json/wp/v2/guide', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/interactive_guide' => __('interactive_guide: https://api.helsingborg.se/event/json/wp/v2/interactive_guide', 'municipio'), + ), + 'default_value' => false, + 'return_format' => 'value', + 'multiple' => 0, + 'allow_custom' => 0, + 'search_placeholder' => '', + 'allow_null' => 0, + 'ui' => 1, + 'ajax' => 1, + 'placeholder' => '', + ), + 2 => array( + 'key' => 'field_653a539bb2fc9', + 'label' => __('Taxonomy Source', 'municipio'), + 'name' => 'taxonomy_source', + 'aria-label' => '', + 'type' => 'select', + 'instructions' => '', + 'required' => 1, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_653a5094a6168', + 'operator' => '==', + 'value' => 'taxonomy', + ), + ), + ), + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'choices' => array( + 'https://skolor.helsingborg.io/wp-json/wp/v2/categories' => __('category: https://skolor.helsingborg.io/wp-json/wp/v2/categories', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/tags' => __('post_tag: https://skolor.helsingborg.io/wp-json/wp/v2/tags', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/menus' => __('nav_menu: https://skolor.helsingborg.io/wp-json/wp/v2/menus', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/area' => __('area: https://skolor.helsingborg.io/wp-json/wp/v2/area', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/usp' => __('usp: https://skolor.helsingborg.io/wp-json/wp/v2/usp', 'municipio'), + 'https://skolor.helsingborg.io/wp-json/wp/v2/grade' => __('grade: https://skolor.helsingborg.io/wp-json/wp/v2/grade', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/categories' => __('category: https://api.helsingborg.se/event/json/wp/v2/categories', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/tags' => __('post_tag: https://api.helsingborg.se/event/json/wp/v2/tags', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/user_groups' => __('user_groups: https://api.helsingborg.se/event/json/wp/v2/user_groups', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/event_categories' => __('event_categories: https://api.helsingborg.se/event/json/wp/v2/event_categories', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/event_tags' => __('event_tags: https://api.helsingborg.se/event/json/wp/v2/event_tags', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/location_categories' => __('location_categories: https://api.helsingborg.se/event/json/wp/v2/location_categories', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/guidegroup' => __('guidegroup: https://api.helsingborg.se/event/json/wp/v2/guidegroup', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/navigation' => __('navigation: https://api.helsingborg.se/event/json/wp/v2/navigation', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/guidetype' => __('guidetype: https://api.helsingborg.se/event/json/wp/v2/guidetype', 'municipio'), + 'https://api.helsingborg.se/event/json/wp/v2/property' => __('property: https://api.helsingborg.se/event/json/wp/v2/property', 'municipio'), + ), + 'default_value' => false, + 'return_format' => 'value', + 'multiple' => 0, + 'allow_custom' => 0, + 'search_placeholder' => '', + 'allow_null' => 0, + 'ui' => 1, + 'ajax' => 1, + 'placeholder' => '', + ), + 3 => array( + 'key' => 'field_653b48052dc15', + 'label' => __('Post Type Arguments', 'municipio'), + 'name' => 'post_type_arguments', + 'aria-label' => '', + 'type' => 'group', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_653a5094a6168', + 'operator' => '==', + 'value' => 'postType', + ), + 1 => array( + 'field' => 'field_653a52d126e03', + 'operator' => '!=empty', + ), + ), + ), + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'layout' => 'block', + 'acfe_seamless_style' => 0, + 'acfe_group_modal' => 0, + 'sub_fields' => array( + 0 => array( + 'key' => 'field_601b9c6128f07', + 'label' => __('Post Type Key', 'municipio'), + 'name' => 'post_type_key', + 'aria-label' => '', + 'type' => 'text', + 'instructions' => __('The key of the post type. Max. 20 characters, cannot contain capital letters or spaces.', 'municipio'), + 'required' => true, + 'conditional_logic' => false, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'maxlength' => '', + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + ), + 1 => array( + 'key' => 'field_65420ddf4476f', + 'label' => __('Label (plural)', 'municipio'), + 'name' => 'label', + 'aria-label' => '', + 'type' => 'text', + 'instructions' => '', + 'required' => 1, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'maxlength' => '', + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + ), + 2 => array( + 'key' => 'field_65420e0644770', + 'label' => __('Label (singular)', 'municipio'), + 'name' => 'labels_singular_name', + 'aria-label' => '', + 'type' => 'text', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'maxlength' => '', + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + ), + 3 => array( + 'key' => 'field_601b9c6128f08', + 'label' => __('Description', 'municipio'), + 'name' => 'description', + 'aria-label' => '', + 'type' => 'textarea', + 'instructions' => __('A short descriptive summary of what the post type is.', 'municipio'), + 'required' => false, + 'conditional_logic' => false, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'new_lines' => '', + 'maxlength' => '', + 'placeholder' => '', + 'rows' => '', + ), + 4 => array( + 'key' => 'field_601b9c6128f09', + 'label' => __('Public', 'municipio'), + 'name' => 'public', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Whether the post type should be publicly queryable.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 5 => array( + 'key' => 'field_601b9c6128f19', + 'label' => __('Hierarchical', 'municipio'), + 'name' => 'hierarchical', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Whether the post type is hierarchical. Allows Parent to be specified.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 6 => array( + 'key' => 'field_601b9c6128f10', + 'label' => __('Show UI', 'municipio'), + 'name' => 'show_ui', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Whether to generate a default UI for managing this post type.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 7 => array( + 'key' => 'field_601b9c6128f11', + 'label' => __('Has Archive', 'municipio'), + 'name' => 'has_archive', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Enables post type archives.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 8 => array( + 'key' => 'field_601b9c6128f12', + 'label' => __('Exclude From Search', 'municipio'), + 'name' => 'exclude_from_search', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Whether to exclude posts with this post type from front end search results.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 9 => array( + 'key' => 'field_601b9c6128f13', + 'label' => __('Publicly Queryable', 'municipio'), + 'name' => 'publicly_queryable', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Whether queries can be performed on the front end as part of parse_request().', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 10 => array( + 'key' => 'field_601b9c6128f14', + 'label' => __('Show In Nav Menus', 'municipio'), + 'name' => 'show_in_nav_menus', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Whether post_type is available for selection in navigation menus.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 11 => array( + 'key' => 'field_601b9c6128f15', + 'label' => __('Show In Menu', 'municipio'), + 'name' => 'show_in_menu', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Where to show the post type in the admin menu. show_ui must be true.', 'municipio'), + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_601b9c6128f10', + 'operator' => '==', + 'value' => '1', + ), + ), + ), + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 12 => array( + 'key' => 'field_601b9c6128f16', + 'label' => __('Show In Admin Bar', 'municipio'), + 'name' => 'show_in_admin_bar', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Where to show the post type in the admin bar. show_in_menu must be true.', 'municipio'), + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_601b9c6128f15', + 'operator' => '==', + 'value' => '1', + ), + ), + ), + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 13 => array( + 'key' => 'field_601b9c6128f21', + 'label' => __('Rewrite', 'municipio'), + 'name' => 'rewrite', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Triggers the handling of rewrites for this post type.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 14 => array( + 'key' => 'field_601b9c6128f17', + 'label' => __('Menu Position', 'municipio'), + 'name' => 'menu_position', + 'aria-label' => '', + 'type' => 'number', + 'instructions' => __('The position in the menu order the post type should appear. show_in_menu must be true.', 'municipio'), + 'required' => false, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_601b9c6128f15', + 'operator' => '==', + 'value' => '1', + ), + ), + ), + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'min' => '', + 'max' => '', + 'step' => '', + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + ), + 15 => array( + 'key' => 'field_601b9c6128f18', + 'label' => __('Capabilities', 'municipio'), + 'name' => 'capabilities', + 'aria-label' => '', + 'type' => 'select', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'choices' => array( + ), + 'default_value' => array( + ), + 'return_format' => 'value', + 'multiple' => 1, + 'allow_custom' => 1, + 'placeholder' => __('eg. "manage_options"...', 'municipio'), + 'allow_null' => 0, + 'ui' => 1, + 'ajax' => 0, + ), + 16 => array( + 'key' => 'field_6544a42c139a9', + 'label' => __('Parent post types', 'municipio'), + 'name' => 'parent_post_types', + 'aria-label' => '', + 'type' => 'posttype_select', + 'instructions' => __('Parent post types are used to determine the permalink and the rewrite rules for this post type. Setting parent post types will affect the rewrite slug by prepending it with the parent post types slug.', 'municipio'), + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_601b9c6128f19', + 'operator' => '==', + 'value' => '1', + ), + ), + ), + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'allow_null' => 1, + 'multiple' => 1, + 'placeholder' => '', + 'disabled' => 0, + 'readonly' => 0, + ), + 17 => array( + 'key' => 'field_653b5d117edbf', + 'label' => __('Rewrite options', 'municipio'), + 'name' => 'rewrite_options', + 'aria-label' => '', + 'type' => 'group', + 'instructions' => __('Triggers the handling of rewrites for this post type.', 'municipio'), + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_601b9c6128f21', + 'operator' => '==', + 'value' => '1', + ), + ), + ), + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'layout' => 'block', + 'acfe_seamless_style' => 0, + 'acfe_group_modal' => 0, + 'sub_fields' => array( + 0 => array( + 'key' => 'field_653b5d227edc0', + 'label' => __('Slug', 'municipio'), + 'name' => 'slug', + 'aria-label' => '', + 'type' => 'text', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '50', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'maxlength' => '', + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + ), + 1 => array( + 'key' => 'field_653b5d627edc1', + 'label' => __('With front', 'municipio'), + 'name' => 'with_front', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '25', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 1, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 2 => array( + 'key' => 'field_653b5d727edc2', + 'label' => __('Feeds', 'municipio'), + 'name' => 'feeds', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '25', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 1, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + ), + ), + 18 => array( + 'key' => 'field_601b9c6128f22', + 'label' => __('Query Var', 'municipio'), + 'name' => 'query_var', + 'aria-label' => '', + 'type' => 'text', + 'instructions' => __('Sets the query_var key for this post type.', 'municipio'), + 'required' => false, + 'conditional_logic' => false, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'maxlength' => '', + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + ), + ), + ), + 4 => array( + 'key' => 'field_6541eda1a37ac', + 'label' => __('Taxonomy Arguments', 'municipio'), + 'name' => 'taxonomy_arguments', + 'aria-label' => '', + 'type' => 'group', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_653a5094a6168', + 'operator' => '==', + 'value' => 'taxonomy', + ), + 1 => array( + 'field' => 'field_653a539bb2fc9', + 'operator' => '!=empty', + ), + ), + ), + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'layout' => 'block', + 'acfe_seamless_style' => 0, + 'acfe_group_modal' => 0, + 'sub_fields' => array( + 0 => array( + 'key' => 'field_6541eda2a37ad', + 'label' => __('Taxonomy key', 'municipio'), + 'name' => 'taxonomy_key', + 'aria-label' => '', + 'type' => 'text', + 'instructions' => __('The key of the post type. Max. 32 characters, cannot contain capital letters or spaces.', 'municipio'), + 'required' => 1, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'maxlength' => '', + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + ), + 1 => array( + 'key' => 'field_654253463faf6', + 'label' => __('Label (Plural)', 'municipio'), + 'name' => 'labels_name', + 'aria-label' => '', + 'type' => 'text', + 'instructions' => __('The key of the post type. Max. 32 characters, cannot contain capital letters or spaces.', 'municipio'), + 'required' => 1, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'maxlength' => '', + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + ), + 2 => array( + 'key' => 'field_654253693faf7', + 'label' => __('Label (Singular)', 'municipio'), + 'name' => 'labels_singular_name', + 'aria-label' => '', + 'type' => 'text', + 'instructions' => __('The key of the post type. Max. 32 characters, cannot contain capital letters or spaces.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'maxlength' => '', + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + ), + 3 => array( + 'key' => 'field_6541ee02a37c0', + 'label' => __('Object Type', 'municipio'), + 'name' => 'object_type', + 'aria-label' => '', + 'type' => 'posttype_select', + 'instructions' => __('Post Types to which this taxonomy should be connected to.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'allow_null' => 1, + 'multiple' => 1, + 'placeholder' => '', + 'disabled' => 0, + 'readonly' => 0, + ), + 4 => array( + 'key' => 'field_6541eda2a37ae', + 'label' => __('Description', 'municipio'), + 'name' => 'description', + 'aria-label' => '', + 'type' => 'textarea', + 'instructions' => __('A short descriptive summary of what the post type is.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'acfe_textarea_code' => 0, + 'maxlength' => '', + 'rows' => '', + 'placeholder' => '', + 'new_lines' => '', + ), + 5 => array( + 'key' => 'field_6541eda2a37af', + 'label' => __('Public', 'municipio'), + 'name' => 'public', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Whether the post type should be publicly queryable.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 6 => array( + 'key' => 'field_6541eda2a37b0', + 'label' => __('Hierarchical', 'municipio'), + 'name' => 'hierarchical', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Whether the post type is hierarchical. Allows Parent to be specified.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 7 => array( + 'key' => 'field_6541eda2a37b1', + 'label' => __('Show UI', 'municipio'), + 'name' => 'show_ui', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Whether to generate a default UI for managing this post type.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 8 => array( + 'key' => 'field_6541ee8c94dac', + 'label' => __('Show Admin Column', 'municipio'), + 'name' => 'show_admin_column', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 9 => array( + 'key' => 'field_6541eda2a37b4', + 'label' => __('Publicly Queryable', 'municipio'), + 'name' => 'publicly_queryable', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Whether queries can be performed on the front end as part of parse_request().', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 10 => array( + 'key' => 'field_6541eda2a37b5', + 'label' => __('Show In Nav Menus', 'municipio'), + 'name' => 'show_in_nav_menus', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Whether post_type is available for selection in navigation menus.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 11 => array( + 'key' => 'field_6541eda2a37b6', + 'label' => __('Show In Menu', 'municipio'), + 'name' => 'show_in_menu', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Where to show the post type in the admin menu. show_ui must be true.', 'municipio'), + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_6541eda2a37b1', + 'operator' => '==', + 'value' => '1', + ), + ), + ), + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 12 => array( + 'key' => 'field_6541eda2a37b7', + 'label' => __('Show In Admin Bar', 'municipio'), + 'name' => 'show_in_admin_bar', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Where to show the post type in the admin bar. show_in_menu must be true.', 'municipio'), + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_6541eda2a37b6', + 'operator' => '==', + 'value' => '1', + ), + ), + ), + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 13 => array( + 'key' => 'field_6541eda2a37b8', + 'label' => __('Rewrite', 'municipio'), + 'name' => 'rewrite', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => __('Triggers the handling of rewrites for this post type.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '20', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 0, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 14 => array( + 'key' => 'field_6541eda2a37ba', + 'label' => __('Capabilities', 'municipio'), + 'name' => 'capabilities', + 'aria-label' => '', + 'type' => 'select', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'choices' => array( + ), + 'default_value' => array( + ), + 'return_format' => 'value', + 'multiple' => 1, + 'allow_custom' => 1, + 'placeholder' => __('eg. "manage_options"...', 'municipio'), + 'allow_null' => 0, + 'ui' => 1, + 'ajax' => 0, + ), + 15 => array( + 'key' => 'field_6541eda2a37bb', + 'label' => __('Rewrite options', 'municipio'), + 'name' => 'rewrite_options', + 'aria-label' => '', + 'type' => 'group', + 'instructions' => __('Triggers the handling of rewrites for this post type.', 'municipio'), + 'required' => 0, + 'conditional_logic' => array( + 0 => array( + 0 => array( + 'field' => 'field_6541eda2a37b8', + 'operator' => '==', + 'value' => '1', + ), + ), + ), + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'layout' => 'block', + 'acfe_seamless_style' => 0, + 'acfe_group_modal' => 0, + 'sub_fields' => array( + 0 => array( + 'key' => 'field_6541eda2a37bc', + 'label' => __('Slug', 'municipio'), + 'name' => 'slug', + 'aria-label' => '', + 'type' => 'text', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '50', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'maxlength' => '', + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + ), + 1 => array( + 'key' => 'field_6541eda2a37bd', + 'label' => __('With front', 'municipio'), + 'name' => 'with_front', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '25', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 1, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + 2 => array( + 'key' => 'field_6541eda2a37be', + 'label' => __('Feeds', 'municipio'), + 'name' => 'feeds', + 'aria-label' => '', + 'type' => 'true_false', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '25', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'default_value' => 1, + 'ui_on_text' => '', + 'ui_off_text' => '', + 'ui' => 1, + ), + ), + ), + 16 => array( + 'key' => 'field_6541eda2a37bf', + 'label' => __('Query Var', 'municipio'), + 'name' => 'query_var', + 'aria-label' => '', + 'type' => 'text', + 'instructions' => __('Sets the query_var key for this post type.', 'municipio'), + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'maxlength' => '', + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + ), + ), + ), + ), + 'location' => array( + 0 => array( + 0 => array( + 'param' => 'post_type', + 'operator' => '==', + 'value' => 'api-resource', + ), + ), + ), + 'menu_order' => 0, + 'position' => 'acf_after_title', + 'style' => 'default', + 'label_placement' => 'left', + 'instruction_placement' => 'label', + 'hide_on_screen' => '', + 'active' => true, + 'description' => '', + 'show_in_rest' => 0, + 'acfe_display_title' => '', + 'acfe_autosync' => array( + 0 => 'php', + 1 => 'json', + ), + 'acfe_form' => 0, + 'acfe_meta' => '', + 'acfe_note' => '', +)); + } \ No newline at end of file diff --git a/library/App.php b/library/App.php index d80fe90d5..ca3efe2f0 100644 --- a/library/App.php +++ b/library/App.php @@ -60,12 +60,19 @@ public function __construct() new \Municipio\Content\IframePosterImage(); /** - * Content from API + * Resources from API */ - $customPostTypesFromApi = new \Municipio\Content\CustomPostTypesFromApi(); - $customTaxonomiesFromApi = new \Municipio\Content\CustomTaxonomiesFromApi(); - $customPostTypesFromApi->addHooks(); - $customTaxonomiesFromApi->addHooks(); + $resourcePostType = new \Municipio\Content\ResourceFromApi\ResourcePostType(); + $resourcePostType->addHooks(); + + $resourceRegistry = new \Municipio\Content\ResourceFromApi\ResourceRegistry(); + $resourceRegistry->initialize(); + + $postTypeQueriesModifier = new \Municipio\Content\ResourceFromApi\PostType\PostTypeQueriesModifier($resourceRegistry); + $postTypeQueriesModifier->addHooks(); + + $taxonomyQueriesModifier = new \Municipio\Content\ResourceFromApi\Taxonomy\TaxonomyQueriesModifier($resourceRegistry); + $taxonomyQueriesModifier->addHooks(); /** * Oembed diff --git a/library/Bootstrap.php b/library/Bootstrap.php index 580d0b5d5..ca6904518 100644 --- a/library/Bootstrap.php +++ b/library/Bootstrap.php @@ -84,6 +84,8 @@ 'options-menu-mega' => 'group_6502be085ee3b', 'options-menu-description' => 'group_650296216899c', 'options-menu-language' => 'group_6141cc9c72cc3', + 'options-api-resources-apis' => 'group_653a1673dc501', + 'resource-fields' => 'group_653a509450198', 'user-author-image' => 'group_56c714b46105e', 'widget-contact' => 'group_56c58bade87dc', 'widget-header-common' => 'group_5a65d5e7e913b', diff --git a/library/Content/CustomPostType.php b/library/Content/CustomPostType.php index efa52fc26..a940227ea 100644 --- a/library/Content/CustomPostType.php +++ b/library/Content/CustomPostType.php @@ -48,8 +48,6 @@ public function registerCustomPostTypes() foreach ($typeDefinitions as $typeDefinition) { - $postTypeFromAPI = $this->isPostTypeFromAPI($typeDefinition); - $labels = array( 'name' => $typeDefinition['post_type_name'], 'singular_name' => $typeDefinition['post_type_name'], @@ -67,12 +65,6 @@ public function registerCustomPostTypes() 'not_found_in_trash' => sprintf(__('No %s found in trash', 'municipio'), $typeDefinition['post_type_name']) ); - $supports = $postTypeFromAPI ? [] : array('title', 'editor'); - - if (!$postTypeFromAPI && !empty($typeDefinition['supports'])) { - $supports = array_merge($typeDefinition['supports'], $supports); - } - $rewrite = ['with_front' => isset($typeDefinition['with_front']) ? $typeDefinition['with_front'] : true]; if (!empty($typeDefinition['slug'])) { @@ -91,7 +83,7 @@ public function registerCustomPostTypes() 'rewrite' => $rewrite, 'capability_type' => 'post', 'hierarchical' => $typeDefinition['hierarchical'], - 'supports' => $supports, + 'supports' => $typeDefinition['supports'], 'menu_position' => (int) $typeDefinition['menu_position'], 'has_archive' => true, 'show_in_rest' => true, diff --git a/library/Content/CustomPostTypesFromApi.php b/library/Content/CustomPostTypesFromApi.php deleted file mode 100644 index 017b0c406..000000000 --- a/library/Content/CustomPostTypesFromApi.php +++ /dev/null @@ -1,219 +0,0 @@ -postTypesFromApi = $this->getPostTypesFromApi(); - $this->postTypesWithParentPostTypes = $this->getPostTypesWithParentPostTypes(); - }, 10); - } - - private function getPostTypesFromApi(): array - { - $typeDefinitions = CustomPostType::getTypeDefinitions(); - $postTypesFromApi = array_filter( - $typeDefinitions, - fn ($typeDefinition) => - isset($typeDefinition['api_source_url']) && - !empty($typeDefinition['api_source_url']) && - filter_var($typeDefinition['api_source_url'], FILTER_VALIDATE_URL) !== false - ); - - return array_map(fn ($postType) => sanitize_title(substr($postType['post_type_name'], 0, 19)), $postTypesFromApi); - } - - private function getPostTypesWithParentPostTypes():array { - - $postTypesWithParentPostTypes = []; - $typeDefinitions = CustomPostType::getTypeDefinitions(); - $matches = array_filter( - $typeDefinitions, - fn ($typeDefinition) => - isset($typeDefinition['parent_post_types']) && !empty($typeDefinition['parent_post_types']) - ); - - if( empty($matches) ) { - return []; - } - - foreach($matches as $match) { - $postType = sanitize_title(substr($match['post_type_name'], 0, 19)); - $postTypesWithParentPostTypes[$postType] = $match['parent_post_types']; - } - - return $postTypesWithParentPostTypes; - } - - public function addHooks(): void - { - add_filter('post_type_link', [$this, 'modifyPostTypeLink'], 10, 2); - add_filter('posts_results', [$this, 'modifyPostsResults'], 10, 2); - add_filter('default_post_metadata', [$this, 'modifyDefaultPostMetadata'], 10, 5); - add_filter('Municipio/Breadcrumbs/Items', [$this, 'modifyBreadcrumbsItems'], 10, 3); - add_filter('Municipio/Content/RestApiPostToWpPost', [$this, 'addParentToPostWithParentPostType'], 10, 3); - - add_action('pre_get_posts', [$this, 'preventSuppressFiltersOnWpQuery'], 200, 1); - add_action('pre_get_posts', [$this, 'preventCacheOnPreGetPosts'], 200, 1); - add_action('init', [$this, 'addRewriteRulesForPostTypesWithParentPostTypes'], 10, 0); - } - - public function modifyPostTypeLink(string $postLink, WP_Post $post) - { - $postType = get_post_type($post); - - if (isset($this->postTypesWithParentPostTypes[$postType])) { - - $parentPost = get_post($post->post_parent); - $parentPostType = $parentPost->post_type; - - if (in_array($parentPostType, $this->postTypesWithParentPostTypes[$postType])) { - $parentPostTypeObject = get_post_type_object($parentPostType); - $postTypeObject = get_post_type_object($postType); - $rewriteSlug = $postTypeObject->rewrite['slug']; - $parentRewriteSlug = $parentPostTypeObject->rewrite['slug']; - $postLink = str_replace($rewriteSlug, $parentRewriteSlug, $postLink); - } - } - - return $postLink; - } - - public function modifyBreadcrumbsItems(?array $pageData, $queriedObject, $queriedObjectData): ?array - { - if (is_null($pageData) || !is_a($queriedObject, 'WP_Post')) { - return $pageData; - } - - // if post type in entity registry - if ( - !isset($this->postTypesWithParentPostTypes[$queriedObject->post_type]) || - !is_array($queriedObject->post_type) || - empty($queriedObject->post_parent) - ) { - return $pageData; - } - - foreach($this->postTypesWithParentPostTypes[$queriedObject->post_type] as $parentPostType) { - - $parentPosts = get_posts(['post__in' => [$queriedObject->post_parent], 'post_type' => $parentPostType, 'suppress_filters' => false]); - - if( !empty($parentPosts) ) { - break; - } - } - - if( empty($parentPosts) ) { - return $pageData; - } - - // Insert new element before the last one in $pageData. - array_splice($pageData, -1, 0, [ - [ - 'label' => $parentPosts[0]->post_title, - 'href' => get_post_permalink($parentPosts[0]), - 'current' => false - ], - ]); - - return $pageData; - } - - public function modifyPostsResults(array $posts, WP_Query $query): array - { - if ( - !$query->get('post_type') || - !in_array($query->get('post_type'), $this->postTypesFromApi) - ) { - return $posts; - } - - if ($query->is_single()) { - $posts = CustomPostTypeFromApi::getSingle($query->get('name'), $query->get('post_type')); - } else { - $posts = CustomPostTypeFromApi::getCollection($query, $query->get('post_type')); - $headers = CustomPostTypeFromApi::getCollectionHeaders($query, $query->get('post_type')); - $query->found_posts = $headers['x-wp-total'] ?? count($posts); - $query->max_num_pages = $headers['x-wp-totalpages'] ?? 1; - } - - return is_array($posts) ? $posts : [$posts]; - } - - public function modifyDefaultPostMetadata($value, $objectId, $metaKey, $single, $metaType) - { - $postType = get_post_type($objectId); - - if (!in_array($postType, $this->postTypesFromApi)) { - return $value; - } - - return CustomPostTypeFromApi::getMeta($objectId, $metaKey, $single, $metaType, $postType) ?? $value; - } - - public function addParentToPostWithParentPostType(WP_Post $wpPost, object $restApiPost, string $postType) - { - if (!isset($this->postTypesWithParentPostTypes[$postType])) { - return $wpPost; - } - - // TODO: replace with real parent from API. - $wpPost->post_parent = $restApiPost->acf->parent_school ?? 0; - - return $wpPost; - } - - public function preventSuppressFiltersOnWpQuery(WP_Query $query): void - { - if (!in_array($query->get('post_type'), $this->postTypesFromApi)) { - return; - } - - $query->query['suppress_filters'] = false; - } - - public function preventCacheOnPreGetPosts(WP_Query $query): void - { - if (!in_array($query->get('post_type'), $this->postTypesFromApi)) { - return; - } - - $query->set('update_post_meta_cache', false); - $query->set('update_post_term_cache', false); - } - - public function addRewriteRulesForPostTypesWithParentPostTypes(): void - { - foreach ($this->postTypesWithParentPostTypes as $postType => $parentPostTypes) { - - if (!post_type_exists($postType)) { - return; - } - - foreach ($parentPostTypes as $parentPostType) { - - if (!post_type_exists($parentPostType)) { - continue; - } - - $parentPostTypeObject = get_post_type_object($parentPostType); - $rewriteSlug = $parentPostTypeObject->rewrite['slug']; - - add_rewrite_rule( - $rewriteSlug . '/(.*)/(.*)', - 'index.php?post_type=' . $postType . '&name=$matches[2]', - 'top' - ); - } - } - } -} diff --git a/library/Content/CustomTaxonomiesFromApi.php b/library/Content/CustomTaxonomiesFromApi.php deleted file mode 100644 index b4ccbc95e..000000000 --- a/library/Content/CustomTaxonomiesFromApi.php +++ /dev/null @@ -1,82 +0,0 @@ -taxonomiesFromApi = $this->getTaxonomiesFromApi(); - }, 10); - } - - private function getTaxonomiesFromApi(): array - { - $taxonomyDefinitions = CustomTaxonomy::getTypeDefinitions(); - - $taxonomiesFromApi = array_filter( - $taxonomyDefinitions, - fn ($taxonomyDefinition) => - isset($taxonomyDefinition['api_source_url']) && - !empty($taxonomyDefinition['api_source_url'] ) && - filter_var($taxonomyDefinition['api_source_url'], FILTER_VALIDATE_URL) !== false - ); - - return array_map(fn ($taxonomyDefinition) => sanitize_title($taxonomyDefinition['label']), $taxonomiesFromApi); - } - - public function addHooks(): void - { - add_action('pre_get_terms', [$this, 'modifyPreGetTerms'], 10, 1); - add_filter('get_terms', [$this, 'modifyGetTerms'], 10, 4); - add_filter('get_object_terms', [$this, 'modifyGetObjectTerms'], 10, 4); - add_filter('Municipio/Archive/getTaxonomyFilters/option/value', [$this, 'modifyGetTaxonomyFiltersOptionValue'], 10, 3); - } - - public function modifyGetTaxonomyFiltersOptionValue(string $value, WP_Term $option, WP_Taxonomy $taxonomy): string - { - if (!is_a($option, 'WP_Term') || !in_array($taxonomy->name, $this->taxonomiesFromApi)) { - return $value; - } - - return $option->term_id; - } - - public function modifyPreGetTerms(WP_Term_Query $termQuery) { - - // If querying a taxonomy that is not from the API, return early - if (!isset($termQuery->query_vars['taxonomy']) || !in_array($termQuery->query_vars['taxonomy'][0], $this->taxonomiesFromApi)) { - return; - } - - // Set suppress filters to false - $termQuery->query_vars['suppress_filters'] = false; - } - - public function modifyGetTerms(array $terms, $taxonomy, array $queryVars, WP_Term_Query $termQuery): array - { - if (!isset($queryVars['taxonomy']) || !in_array($queryVars['taxonomy'][0], $this->taxonomiesFromApi)) { - return $terms; - } - - return CustomTaxonomyFromApi::getCollection($termQuery, $queryVars['taxonomy'][0]); - } - - public function modifyGetObjectTerms(array $terms, array $objectIds, array $taxonomies, array $queryVars): array - { - if (!isset($queryVars['taxonomy']) || !in_array($queryVars['taxonomy'][0], $this->taxonomiesFromApi)) { - return $terms; - } - - $termQuery = new WP_Term_Query($queryVars); - - return CustomTaxonomyFromApi::getCollection($termQuery, $queryVars['taxonomy'][0]); - } -} diff --git a/library/Content/CustomTaxonomyFromApi.php b/library/Content/CustomTaxonomyFromApi.php deleted file mode 100644 index ab0c33d78..000000000 --- a/library/Content/CustomTaxonomyFromApi.php +++ /dev/null @@ -1,110 +0,0 @@ - - isset($taxonomyDefinition['api_source_url']) && !empty($taxonomyDefinition['api_source_url']) - ); - - foreach ($taxonomiesFromApi as $taxonomy) { - self::$taxonomies[sanitize_title($taxonomy['label'])] = $taxonomy['api_source_url']; - } - } - - public static function getSingle($id, string $taxonomy): ?WP_Term - { - $url = self::getSingleUrl($id, $taxonomy); - - if (empty($url)) { - return null; - } - - $termFromApi = RestRequestHelper::getFromApi($url); - - if (is_wp_error($termFromApi)) { - return new WP_Term(new \stdClass()); - } - - return self::convertRestApiTermToWPTerm($termFromApi, $taxonomy); - } - - public static function getCollection(?WP_Term_Query $termQuery, $taxonomy): array - { - $url = self::getCollectionUrl($taxonomy); - - if (empty($url)) { - return []; - } - - $restParams = !empty($termQuery) - ? '?' . WPTermQueryToRestParamsConverter::convertToRestParamsString($termQuery->query_vars) - : ''; - - $termsFromApi = RestRequestHelper::getFromApi($url . $restParams); - - if (is_wp_error($termsFromApi) || !is_array($termsFromApi)) { - return []; - } - - return array_map(fn ($termFromApi) => self::convertRestApiTermToWPTerm($termFromApi, $taxonomy), $termsFromApi); - } - - private static function getSingleUrl($id, string $taxonomy): ?string - { - $url = self::getCollectionUrl($taxonomy); - - if (empty($url)) { - return null; - } - - return "{$url}/{$id}"; - } - - private static function convertRestApiTermToWPTerm(object $termFromApi, string $taxonomyName): WP_Term - { - $term = new WP_Term(new \stdClass()); - $term->term_id = $termFromApi->id; - $term->name = $termFromApi->name; - $term->slug = $termFromApi->slug; - $term->term_group = $termFromApi->term_group ?? 0; - $term->term_taxonomy_id = $termFromApi->taxonomy_id ?? 0; - $term->taxonomy = $taxonomyName; - $term->description = $termFromApi->description ?? ''; - $term->parent = $termFromApi->parent ?? 0; - $term->count = $termFromApi->count ?? 0; - $term->filter = 'raw'; - - return $term; - } -} diff --git a/library/Content/ResourceFromApi/PostType/PostTypeQueriesModifier.php b/library/Content/ResourceFromApi/PostType/PostTypeQueriesModifier.php new file mode 100644 index 000000000..e5ea3c615 --- /dev/null +++ b/library/Content/ResourceFromApi/PostType/PostTypeQueriesModifier.php @@ -0,0 +1,293 @@ +resourceRegistry = $resourceRegistry; + } + + public function addHooks(): void + { + add_filter('post_type_link', [$this, 'modifyPostTypeLink'], 10, 2); + add_filter('posts_results', [$this, 'modifyPostsResults'], 10, 2); + add_filter('default_post_metadata', [$this, 'modifyDefaultPostMetadata'], 100, 5); + add_filter('acf/pre_load_value', [$this, 'preLoadAcfValue'], 10, 3); + add_filter('Municipio/Breadcrumbs/Items', [$this, 'modifyBreadcrumbsItems'], 10, 3); + add_action('pre_get_posts', [$this, 'preventSuppressFiltersOnWpQuery'], 200, 1); + add_action('pre_get_posts', [$this, 'preventCacheOnPreGetPosts'], 200, 1); + add_action('Municipio/Content/ResourceFromApi/ConvertRestApiPostToWPPost', [$this, 'addParentToPost'], 10, 3); + } + + public function preLoadAcfValue($value, $postId, $field) + { + if (!isset($field['name']) || !$this->isRemotePostId($postId)) { + return $value; + } + + $registeredPostType = $this->getResourceFromPostId($postId); + $postId = (int)str_replace((string)$registeredPostType->resourceID, '', (string)absint($postId)); + + return PostTypeResourceRequest::getMeta($postId, $field['name'], $registeredPostType) ?? $value; + } + + public function modifyBreadcrumbsItems(?array $pageData, $queriedObject, $queriedObjectData): ?array + { + if (is_null($pageData) || !is_a($queriedObject, 'WP_Post')) { + return $pageData; + } + + $registeredPostType = $this->resourceRegistry->getRegisteredPostType($queriedObject->post_type); + + if (empty($registeredPostType)) { + return $pageData; + } + + if ($queriedObject->post_parent === 0) { + return $pageData; + } + + $parentPosts = get_posts(['post__in' => [$queriedObject->post_parent], 'suppress_filters' => false]); + + if (empty($parentPosts)) { + return $pageData; + } + + array_splice($pageData, -1, 0, [ + [ + 'label' => $parentPosts[0]->post_title, + 'href' => get_post_permalink($parentPosts[0]), + 'current' => false + ], + ]); + + return $pageData; + } + + public function modifyPostTypeLink(string $postLink, WP_Post $post) + { + if ($post->post_parent === 0) { + return $postLink; + } + + $registeredPostType = $this->resourceRegistry->getRegisteredPostType($post->post_type); + $postTypeObject = get_post_type_object($post->post_type); + + if (empty($registeredPostType) || empty($postTypeObject)) { + return $postLink; + } + + if (!str_starts_with($postTypeObject->rewrite['slug'], '/%parentPost%')) { + return $postLink; + } + + $path = trim(parse_url(get_post_permalink($post->post_parent))['path'], '/'); + $postLink = str_replace('%parentPost%', $path, $postLink); + + return $postLink; + } + + public function modifyPostsResults(array $posts, WP_Query $query): array + { + $registeredPostType = $this->getResourceFromQuery($query); + + if (empty($registeredPostType)) { + return $posts; + } + + if ($query->is_single()) { + $posts = PostTypeResourceRequest::getSingle($query->get('name'), $registeredPostType); + } else { + $queryVars = $this->prepareQueryArgsForRequest($query->query_vars, $registeredPostType); + $posts = PostTypeResourceRequest::getCollection($registeredPostType, $queryVars); + $headers = PostTypeResourceRequest::getCollectionHeaders($registeredPostType, $queryVars); + $query->found_posts = $headers['x-wp-total'] ?? count($posts); + $query->max_num_pages = $headers['x-wp-totalpages'] ?? 1; + } + + return is_array($posts) ? $posts : [$posts]; + } + + private function getResourceFromQuery(WP_Query $query): ?object + { + if ($query->get('post__in') && !empty($query->get('post__in'))) { + + $ids = $query->get('post__in'); + + if ($this->containsIdFromResource($ids)) { + return $this->getResourceFromPostId($ids[0]); + } + } + + if ($query->get('post_type') && is_string($query->get('post_type'))) { + return $this->resourceRegistry->getRegisteredPostType($query->get('post_type')); + } + + return null; + } + + private function containsIdFromResource(array $ids): bool + { + foreach ($ids as $id) { + if ($this->isRemotePostId((int)$id)) { + return true; + } + } + + return false; + } + + public function modifyDefaultPostMetadata($value, int $objectId, $metaKey, $single, $metaType) + { + $registeredPostType = $this->getResourceFromPostId($objectId); + + if (is_null($registeredPostType)) { + return $value; + } + + $objectId = $this->prepareIdForRequest($objectId, $registeredPostType); + + return PostTypeResourceRequest::getMeta($objectId, $metaKey, $registeredPostType, $single) ?? $value; + } + + private function prepareQueryArgsForRequest(array $queryArgs, object $resource): array + { + if (isset($queryArgs['post__in']) && !empty(array_filter($queryArgs['post__in']))) { + $queryArgs['post__in'] = array_map( + fn ($id) => $this->prepareIdForRequest($id, $resource), + $queryArgs['post__in'] + ); + } + + return $queryArgs; + } + + private function prepareIdForRequest(int $id, object $resource): int + { + return (int)str_replace((string)$resource->resourceID, '', (string)absint($id)); + } + + public function preventSuppressFiltersOnWpQuery(WP_Query $query): void + { + if (!$query->get('post_type') || !is_string($query->get('post_type'))) { + return; + } + + $registeredPostType = $this->resourceRegistry->getRegisteredPostType($query->get('post_type')); + + if (empty($registeredPostType)) { + return; + } + + $query->query['suppress_filters'] = false; + } + + public function preventCacheOnPreGetPosts(WP_Query $query): void + { + if (!$query->get('post_type') || !is_string($query->get('post_type'))) { + return; + } + + $registeredPostType = $this->resourceRegistry->getRegisteredPostType($query->get('post_type')); + + if (empty($registeredPostType)) { + return; + } + + $query->set('update_post_meta_cache', false); + $query->set('update_post_term_cache', false); + } + + private function getResourceFromPostId($postId): ?object + { + + if (!$this->isRemotePostId((int)$postId)) { + return null; + } + + $registeredPostTypes = $this->resourceRegistry->getRegisteredPostTypes(); + + if (empty($registeredPostTypes)) { + return null; + } + + foreach ($registeredPostTypes as $registeredPostType) { + $needle = (string)$registeredPostType->resourceID; + $haystack = (string)absint($postId); + + if (str_starts_with($haystack, $needle)) { + return $registeredPostType; + } + } + + return null; + } + + private function isRemotePostId($id): bool + { + return is_numeric($id) && (int)$id < 0; + } + + public function addParentToPost($wpPost, $restApiPost, $localPostType) + { + + if ($wpPost->post_parent === 0) { + return $wpPost; + } + + if (!isset($restApiPost->_links) || !isset($restApiPost->_links->up)) { + return $wpPost; + } + + $parentUrl = $restApiPost->_links->up[0]->href; + + if (empty($parentUrl)) { + return $wpPost; + } + + // Get parent post from API and convert to WP_Post. Then use the id from that WP_Post as the parent id for $wpPost. + $parentPostFromApi = RestRequestHelper::getFromApi($parentUrl); + $parentId = $parentPostFromApi->id; + $parentResource = null; + + if (!isset($parentPostFromApi->_links) || !isset($parentPostFromApi->_links->collection)) { + return $wpPost; + } + + $parentCollectionUrl = $parentPostFromApi->_links->collection[0]->href; + + $resources = $this->resourceRegistry->getRegisteredPostTypes(); + + foreach ($resources as $resource) { + if ($resource->collectionUrl === $parentCollectionUrl) { + $parentResource = $resource; + break; + } + } + + if (empty($parentResource)) { + return $wpPost; + } + + $parentPost = PostTypeResourceRequest::getSingle($parentId, $parentResource); + + if (empty($parentPost)) { + return $wpPost; + } + + $localParentId = $parentPost->ID; + $wpPost->post_parent = $localParentId; + + return $wpPost; + } +} diff --git a/library/Content/ResourceFromApi/PostType/PostTypeRegistrar.php b/library/Content/ResourceFromApi/PostType/PostTypeRegistrar.php new file mode 100644 index 000000000..3ec81b8b0 --- /dev/null +++ b/library/Content/ResourceFromApi/PostType/PostTypeRegistrar.php @@ -0,0 +1,178 @@ +name = $name; + $this->arguments = $arguments; + } + + /** + * Registers the post type. + * + * @return void + */ + public function register(): void + { + $this->prepareArguments(); + $this->registerPostType(); + } + + /** + * Get the name of the post type. + * + * @return string The name of the post type. + */ + public function getName(): string + { + return $this->name; + } + + /** + * Get the arguments for registering the post type. + * + * @return array The arguments for registering the post type. + */ + public function getArguments(): array + { + return $this->arguments; + } + + /** + * Check if the post type is registered. + * + * @return bool True if the post type is registered, false otherwise. + */ + public function isRegistered(): bool + { + return $this->registered; + } + + /** + * Registers a custom post type. + * + * @access private + * @return void + */ + private function registerPostType() + { + $success = register_post_type($this->name, $this->arguments); + + if (is_a($success, WP_Post_Type::class)) { + $this->registered = true; + } + } + + /** + * Prepare the arguments for registering a custom post type. + * + * @return void + */ + private function prepareArguments(): void + { + $preparedArguments = $this->arguments; + $preparedArguments = $this->prepareLabels($preparedArguments); + $preparedArguments = $this->prepareQueryVar($preparedArguments); + $preparedArguments = $this->prepareRewrite($preparedArguments); + $preparedArguments = $this->prepareParentPostTypes($preparedArguments); + + $this->arguments = $preparedArguments; + } + + /** + * Prepare labels for the post type. + * + * @param array $arguments The arguments for the post type. + * @return array The prepared labels. + */ + private function prepareLabels(array $arguments): array + { + if (isset($arguments['labels_singular_name']) && !empty($arguments['labels_singular_name'])) { + $arguments['labels'] = ['singular_name' => $arguments['labels_singular_name']]; + } + + return $arguments; + } + + /** + * Prepare the query variable. + * + * @param array $arguments The arguments to prepare. + * @return array The prepared query variable. + */ + private function prepareQueryVar(array $arguments): array + { + if (empty($arguments['query_var'])) { + unset($arguments['query_var']); + } + + return $arguments; + } + + /** + * Prepare the rewrite rules for a post type. + * + * @param array $arguments The arguments for the post type. + * @return array The modified arguments with the rewrite rules prepared. + */ + private function prepareRewrite(array $arguments): array + { + if ($arguments['rewrite'] === true) { + $arguments['rewrite'] = $arguments['rewrite_options']; + + if (empty($arguments['rewrite_options']['slug'])) { + unset($arguments['rewrite']['slug']); + } + } + + return $arguments; + } + + /** + * Prepare parent post types. + * + * If the post type is not hierarchical and has parent post types, add parent post slug to the rewrite slug. + * + * @param array $arguments The post type arguments. + * @return array The modified post type arguments. + */ + private function prepareParentPostTypes(array $arguments): array + { + if (!$arguments['hierarchical'] && !empty($arguments['parent_post_types'])) { + $parentSlug = '/%parentPost%'; + $slug = ''; + + if (isset($arguments['rewrite']) && isset($arguments['rewrite']['slug'])) { + $slug = $arguments['rewrite']['slug']; + $slug = ltrim($slug, '/'); + } + + $arguments['rewrite']['slug'] = "{$parentSlug}{$slug}"; + } + + return $arguments; + } +} diff --git a/library/Content/CustomPostTypeFromApi.php b/library/Content/ResourceFromApi/PostType/PostTypeResourceRequest.php similarity index 58% rename from library/Content/CustomPostTypeFromApi.php rename to library/Content/ResourceFromApi/PostType/PostTypeResourceRequest.php index dad189f76..a7393532d 100644 --- a/library/Content/CustomPostTypeFromApi.php +++ b/library/Content/ResourceFromApi/PostType/PostTypeResourceRequest.php @@ -1,20 +1,18 @@ self::convertRestApiPostToWPPost((object)$post, $postType), + fn ($post) => self::convertRestApiPostToWPPost((object)$post, $resource), $postsFromApi ); } - public static function getCollectionHeaders(?WP_Query $wpQuery, $postType): array - { - $url = self::getCollectionUrl($postType, $wpQuery); - - if (empty($url)) { - return []; - } - - $headers = RestRequestHelper::getHeadersFromApi($url); - - if (is_wp_error($headers) || !is_array($headers)) { - return []; - } - - return $headers; - } - - public static function getSingle($id, string $postType): ?WP_Post + public static function getSingle($id, object $resource): ?object { - $url = self::getSingleUrl($id, $postType); + $url = self::getSingleUrl($id, $resource); if (empty($url)) { return null; @@ -59,35 +40,39 @@ public static function getSingle($id, string $postType): ?WP_Post $postFromApi = RestRequestHelper::getFromApi($url); - if (is_wp_error($postFromApi) || !$postFromApi) { + if (is_wp_error($postFromApi)) { return null; } - $postFromApi = is_array($postFromApi) - ? $postFromApi[0] - : $postFromApi; + if (is_array($postFromApi)) { + return self::convertRestApiPostToWPPost($postFromApi[0], $resource); + } else if (is_object($postFromApi)) { + return self::convertRestApiPostToWPPost($postFromApi, $resource); + } - return self::convertRestApiPostToWPPost($postFromApi, $postType); + return null; } - private static function getSingleUrl($id, string $postType): ?string + public static function getCollectionHeaders(object $resource, ?array $queryArgs): array { - $url = self::getCollectionUrl($postType); + $url = self::getCollectionUrl($resource, $queryArgs); if (empty($url)) { - return null; + return []; } - if (is_numeric($id)) { - return "{$url}/{$id}"; + $headers = RestRequestHelper::getHeadersFromApi($url); + + if (is_wp_error($headers) || !is_array($headers)) { + return []; } - return "{$url}/?slug={$id}"; + return $headers; } - public static function getMeta(int $objectId, string $metaKey, bool $single = true, string $metaType = 'post', string $postType) + public static function getMeta(int $id, string $metaKey, object $resource, bool $single = true) { - $url = self::getSingleUrl($objectId, $postType); + $url = self::getSingleUrl($id, $resource); $postFromApi = RestRequestHelper::getFromApi($url); if (isset($postFromApi->acf) && isset($postFromApi->acf->$metaKey)) { @@ -109,49 +94,48 @@ public static function getMeta(int $objectId, string $metaKey, bool $single = tr return null; } - private static function setupPostTypes(): void + private static function getSingleUrl($id, object $resource): ?string { - $typeDefinitions = CustomPostType::getTypeDefinitions(); - $postTypesFromApi = array_filter( - $typeDefinitions, - fn ($typeDefinition) => - isset($typeDefinition['api_source_url']) && !empty($typeDefinition['api_source_url']) - ); - if (empty($postTypesFromApi)) { - return; - } + $collectionUrl = self::getCollectionUrl($resource); - foreach ($postTypesFromApi as $postType) { - $postTypeName = sanitize_title(substr($postType['post_type_name'], 0, 19)); - self::$postTypes[$postTypeName] = $postType['api_source_url']; + if (is_numeric($id)) { + return trailingslashit($collectionUrl) . $id; } + + return "{$collectionUrl}/?slug={$id}"; } - private static function getCollectionUrl(string $postType, ?WP_Query $wpQuery = null): ?string + private static function getCollectionUrl(object $resource, ?array $queryArgs = null): ?string { - if (self::$postTypes === null) { - self::setupPostTypes(); - } + $resourceUrl = get_field('post_type_source', $resource->resourceID); - if (!isset(self::$postTypes[$postType])) { + if (empty($resourceUrl)) { return null; } - $restParams = !empty($wpQuery) - ? '?' . WPQueryToRestParamsConverter::convertToRestParamsString($wpQuery->query_vars) + $restParams = !empty($queryArgs) + ? '?' . WPQueryToRestParamsConverter::convertToRestParamsString($queryArgs) : ''; - return self::$postTypes[$postType] . $restParams; + return $resourceUrl . $restParams; + } + + private static function getLocalID(int $id, object $resource): int + { + return -(int)"{$resource->resourceID}{$id}"; } /** * @param stdClass $restApiPost */ - private static function convertRestApiPostToWPPost(stdClass $restApiPost, string $postType): WP_Post + private static function convertRestApiPostToWPPost(stdClass $restApiPost, object $resource): WP_Post { + $localID = self::getLocalID($restApiPost->id, $resource); + $localPostType = $resource->name; + $wpPost = new WP_Post((object)[]); - $wpPost->ID = $restApiPost->id; + $wpPost->ID = $localID; $wpPost->post_author = $restApiPost->author ?? 1; $wpPost->post_date = $restApiPost->date ?? ''; $wpPost->post_date_gmt = $restApiPost->date_gmt ?? ''; @@ -171,11 +155,11 @@ private static function convertRestApiPostToWPPost(stdClass $restApiPost, string $wpPost->post_parent = $restApiPost->parent ?? 0; $wpPost->guid = $restApiPost->guid->rendered ?? ''; $wpPost->menu_order = $restApiPost->menu_order ?? 0; - $wpPost->post_type = $postType; + $wpPost->post_type = $localPostType; $wpPost->post_mime_type = $restApiPost->mime_type ?? ''; $wpPost->comment_count = 0; $wpPost->filter = 'raw'; - return apply_filters('Municipio/Content/RestApiPostToWpPost', $wpPost, $restApiPost, $postType); + return apply_filters('Municipio/Content/ResourceFromApi/ConvertRestApiPostToWPPost', $wpPost, $restApiPost, $localPostType); } } diff --git a/library/Content/ResourceFromApi/QueriesModifierInterface.php b/library/Content/ResourceFromApi/QueriesModifierInterface.php new file mode 100644 index 000000000..06191381d --- /dev/null +++ b/library/Content/ResourceFromApi/QueriesModifierInterface.php @@ -0,0 +1,9 @@ + __('API Resources', 'municipio'), + 'labels' => [ + 'singular_name' => __('API Resource', 'municipio'), + ], + 'show_ui' => true, + 'public' => false, + 'has_archive' => false, + 'show_in_rest' => false, + 'supports' => false, + 'taxonomies' => [], + ] + ); + } + + public function addOptionsPage() + { + if (function_exists('acf_add_options_page')) { + acf_add_options_page(array( + 'page_title' => 'Api:s', + 'menu_title' => 'Api:s', + 'menu_slug' => 'api-resource-apis', + 'capability' => 'manage_options', + 'redirect' => false, + 'parent_slug' => 'edit.php?post_type=api-resource', + )); + } + } + + public function loadPostTypeSourceOptions($field) + { + + $choices = []; + + if (!function_exists('get_field')) { + return $field; + } + + $endpoints = get_field('api_resources_apis', 'options'); + + if (empty($endpoints)) { + return $field; + } + + $urls = array_map(fn ($row) => $row['url'], $endpoints); + $urls = array_filter($urls, fn ($url) => filter_var($url, FILTER_VALIDATE_URL) !== false); + + if (empty($urls)) { + return $field; + } + + foreach ($urls as $url) { + + $typesFromApi = RestRequestHelper::getFromApi(trailingslashit($url) . 'types'); + + if (is_wp_error($typesFromApi) || empty($typesFromApi)) { + return null; + } + + foreach ($typesFromApi as $type) { + if ( + !isset($type->slug) || + !isset($type->_links) || + !isset($type->_links->collection) || + empty($type->_links->collection) || + !isset($type->_links->collection[0]->href) || + !filter_var($type->_links->collection[0]->href, FILTER_VALIDATE_URL) + ) { + continue; + } + + $value = trailingslashit($url) . $type->rest_base; + $label = "{$type->slug}: {$value}"; + $choices[$value] = $label; + } + } + + if (!empty($choices)) { + $field['choices'] = $choices; + } + + return $field; + } + + public function loadTaxonomySourceOptions($field) + { + + $choices = []; + + if (!function_exists('get_field')) { + return $field; + } + + $endpoints = get_field('api_resources_apis', 'options'); + + if (empty($endpoints)) { + return $field; + } + + $urls = array_map(fn ($row) => $row['url'], $endpoints); + $urls = array_filter($urls, fn ($url) => filter_var($url, FILTER_VALIDATE_URL) !== false); + + if (empty($urls)) { + return $field; + } + + foreach ($urls as $url) { + + $typesFromApi = RestRequestHelper::getFromApi(trailingslashit($url) . 'taxonomies'); + + if (is_wp_error($typesFromApi) || empty($typesFromApi)) { + return null; + } + + foreach ($typesFromApi as $type) { + if ( + !isset($type->slug) || + !isset($type->_links) || + !isset($type->_links->collection) || + empty($type->_links->collection) || + !isset($type->_links->collection[0]->href) || + !filter_var($type->_links->collection[0]->href, FILTER_VALIDATE_URL) + ) { + continue; + } + + $value = trailingslashit($url) . $type->rest_base; + $label = "{$type->slug}: {$value}"; + $choices[$value] = $label; + } + } + + if (!empty($choices)) { + $field['choices'] = $choices; + } + + return $field; + } + + public function setPostTypeResourcePostTitleFromAcf($postId) + { + $postTypeArguments = get_field('post_type_arguments', $postId); + + if ( + empty($postTypeArguments) || + !isset($postTypeArguments['post_type_key']) || + empty($postTypeArguments['post_type_key']) + ) { + return; + } + + $postTypeName = $postTypeArguments['post_type_key']; + $postTypeName = sanitize_title(substr($postTypeName, 0, 19)); + + wp_update_post([ + 'ID' => $postId, + 'post_title' => $postTypeName, + 'post_name' => $postTypeName, + + ]); + } + + public function setTaxonomyResourcePostTitleFromAcf($postId) + { + $taxonomyArguments = get_field('taxonomy_arguments', $postId); + + if ( + empty($taxonomyArguments) || + !isset($taxonomyArguments['taxonomy_key']) || + empty($taxonomyArguments['taxonomy_key']) + ) { + return; + } + + $taxonomyName = $taxonomyArguments['taxonomy_key']; + $taxonomyName = sanitize_title(substr($taxonomyName, 0, 31)); + + wp_update_post([ + 'ID' => $postId, + 'post_title' => $taxonomyName, + 'post_name' => $taxonomyName, + + ]); + } + + public function sanitizePostTypeKeyBeforeSave($value, $postId, $field, $originalValue) + { + return sanitize_title(substr($value, 0, 19)); + } + + public function sanitizeTaxonomyKeyBeforeSave($value, $postId, $field, $originalValue) + { + return sanitize_title(substr($value, 0, 31)); + } +} diff --git a/library/Content/ResourceFromApi/ResourceRegistry.php b/library/Content/ResourceFromApi/ResourceRegistry.php new file mode 100644 index 000000000..477e1f262 --- /dev/null +++ b/library/Content/ResourceFromApi/ResourceRegistry.php @@ -0,0 +1,276 @@ +postTypes = []; + self::$registry->taxonomies = []; + self::$registry->attachments = []; + + $this->registerPostTypes(); + $this->registerPostTypesRewriteRules(); + $this->registerTaxonomies(); + } + + public function getRegisteredPostTypes(): array + { + return self::$registry->postTypes; + } + + public function getRegisteredPostType(string $postTypeName): ?object + { + if (empty(self::$registry->postTypes)) { + return null; + } + + foreach (self::$registry->postTypes as $postType) { + if ($postType->name === $postTypeName) { + return $postType; + } + } + + return null; + } + + public function getRegisteredTaxonomy(string $taxonomyName): ?object + { + if (empty(self::$registry->taxonomies)) { + return null; + } + + foreach (self::$registry->taxonomies as $taxonomy) { + if ($taxonomy->name === $taxonomyName) { + return $taxonomy; + } + } + + return null; + } + + public function getRegisteredTaxonomies(): array + { + return self::$registry->taxonomies; + } + + public function getRegisteredAttachments(): array + { + return self::$registry->attachments; + } + + private function registerPostTypes() + { + $postTypes = $this->getPostTypes(); + + if (empty($postTypes)) { + return; + } + + foreach ($postTypes as $postType) { + + if ( + empty($postType->name) || + empty($postType->arguments) || + empty($postType->resourceID) + ) { + continue; + } + + $registrar = new PostTypeRegistrar($postType->name, $postType->arguments); + $registrar->register($postType->name, $postType->arguments); + + if ($registrar->isRegistered()) { + self::$registry->postTypes[] = $postType; + } + } + } + + private function registerPostTypesRewriteRules() { + $postTypes = $this->getPostTypes(); + foreach($postTypes as $postType) { + $this->addRewriteRules($postType->name, $postType->arguments); + } + } + + private function addRewriteRules(string $postTypeName, array $arguments):void { + + if ($arguments['hierarchical'] === true || empty($arguments['parent_post_types'])) { + return; + } + + foreach($arguments['parent_post_types'] as $parentPostTypeName) { + + if ($arguments['hierarchical'] === true || empty($arguments['parent_post_types'])) { + return; + } + + foreach($arguments['parent_post_types'] as $parentPostTypeName) { + + $parentPostTypeObject = get_post_type_object($parentPostTypeName); + + if( empty($parentPostTypeObject) ) { + continue; + } + + $parentRewriteSlug = $parentPostTypeObject->rewrite['slug']; + + add_rewrite_rule( + $parentRewriteSlug . '/(.*)/(.*)', + 'index.php?'.$postTypeName . '=$matches[2]', + 'top' + ); + } + } + } + + private function registerTaxonomies() { + $taxonomies = $this->getTaxonomies(); + + if (empty($taxonomies)) { + return; + } + + foreach ($taxonomies as $taxonomy) { + + if ( + empty($taxonomy->name) || + empty($taxonomy->arguments) || + empty($taxonomy->resourceID) + ) { + continue; + } + + $registrar = new TaxonomyRegistrar($taxonomy->name, $taxonomy->arguments); + $registrar->register($taxonomy->name, $taxonomy->arguments); + + if ($registrar->isRegistered()) { + self::$registry->taxonomies[] = $taxonomy; + } + } + } + + private function getPostTypes(): array + { + $resources = $this->getResourcesByType('postType'); + + if (empty($resources)) { + return []; + } + + return array_map(function ($resource) { + $arguments = $this->getPostTypeArguments($resource->ID); + $name = $this->getPostTypeName($resource->ID); + $resourceID = $resource->ID; + $collectionUrl = self::getCollectionUrl($resourceID, 'postType'); + + return (object)['name' => $name, 'resourceID' => $resourceID, 'arguments' => $arguments, 'collectionUrl' => $collectionUrl]; + }, $resources); + } + + private function getTaxonomies(): array { + $resources = $this->getResourcesByType('taxonomy'); + + if (empty($resources)) { + return []; + } + + return array_map(function ($resource) { + $arguments = $this->getTaxonomyArguments($resource->ID); + $name = $this->getTaxonomyName($resource->ID); + $resourceID = $resource->ID; + $collectionUrl = self::getCollectionUrl($resourceID, 'taxonomy'); + + return (object)['name' => $name, 'resourceID' => $resourceID, 'arguments' => $arguments, 'collectionUrl' => $collectionUrl]; + }, $resources); + } + + private function getResourcesByType(string $type): array + { + if (!in_array($type, ['postType', 'taxonomy', 'attachment'])) { + return []; + } + + return get_posts([ + 'post_type' => $this->resourcePostTypeName, + 'meta_key' => 'type', + 'meta_value' => $type, + 'posts_per_page' => -1, + ]); + } + + private function getPostTypeArguments(int $resourceId): array + { + if (!function_exists('get_field')) { + return []; + } + + return get_field('post_type_arguments', $resourceId) ?? []; + } + + private function getCollectionUrl(int $resourceId, string $type = 'postType'): ?string + { + if (!function_exists('get_field')) { + return null; + } + + $fieldName = $type === 'postType' ? 'post_type_source' : 'taxonomy_source'; + $resourceUrl = get_field($fieldName, $resourceId); + + if (empty($resourceUrl)) { + return null; + } + + return $resourceUrl; + } + + public function getTaxonomyArguments(int $resourceId): array { + if (!function_exists('get_field')) { + return []; + } + + return get_field('taxonomy_arguments', $resourceId) ?? []; + } + + private function getPostTypeName(int $resourceId) { + if (!function_exists('get_field')) { + return ''; + } + + $arguments = $this->getPostTypeArguments($resourceId); + + if( isset($arguments['post_type_key']) ) { + return $arguments['post_type_key']; + } + + return ''; + } + + private function getTaxonomyName(int $resourceId) { + if (!function_exists('get_field')) { + return ''; + } + + $arguments = $this->getTaxonomyArguments($resourceId); + + if( isset($arguments['taxonomy_key']) ) { + return $arguments['taxonomy_key']; + } + + return ''; + } +} diff --git a/library/Content/ResourceFromApi/ResourceRegistryInterface.php b/library/Content/ResourceFromApi/ResourceRegistryInterface.php new file mode 100644 index 000000000..1ccaef2e2 --- /dev/null +++ b/library/Content/ResourceFromApi/ResourceRegistryInterface.php @@ -0,0 +1,12 @@ +resourceRegistry = $resourceRegistry; + } + + public function addHooks(): void + { + // add_action('pre_get_terms', [$this, 'modifyPreGetTerms'], 10, 1); + add_filter('get_terms', [$this, 'modifyGetTerms'], 10, 4); + add_filter('get_object_terms', [$this, 'modifyGetObjectTerms'], 10, 4); + add_filter('Municipio/Archive/getTaxonomyFilters/option/value', [$this, 'modifyGetTaxonomyFiltersOptionValue'], 10, 3); + } + + public function modifyGetTaxonomyFiltersOptionValue(string $value, WP_Term $option, WP_Taxonomy $taxonomy): string + { + $resource = $this->resourceRegistry->getRegisteredTaxonomy($taxonomy->name); + + if (empty($resource)) { + return $value; + } + + return $option->term_id; + } + + public function modifyPreGetTerms(WP_Term_Query $termQuery) { + + // If querying a taxonomy that is not from the API, return early + if ( + !isset($termQuery->query_vars['taxonomy']) || + empty($this->resourceRegistry->getRegisteredTaxonomy($termQuery->query_vars['taxonomy'][0])) + ) { + return; + } + + // Set suppress filters to false + $termQuery->query_vars['suppress_filters'] = false; + } + + public function modifyGetTerms(array $terms, $taxonomy, array $queryVars, WP_Term_Query $termQuery): array + { + if (!isset($queryVars['taxonomy'])) { + return $terms; + } + + $resource = $this->resourceRegistry->getRegisteredTaxonomy($queryVars['taxonomy'][0]); + + if(empty($resource)) { + return $terms; + } + + if( isset($queryVars['object_ids']) && !empty($queryVars['object_ids']) ) { + $queryVars['object_ids'] = array_map(function($objectId){ + + $objectResource = $this->getResourceFromObjectId($objectId); + + if( empty($objectResource) ) { + return null; + } + + return (int)str_replace($objectResource->resourceID, '', (string)absint($objectId)); + + }, $queryVars['object_ids']); + + array_filter($queryVars['object_ids']); + } + + $collection = TaxonomyResourceRequest::getCollection($resource, $queryVars); + + return $collection; + } + + public function modifyGetObjectTerms(array $terms, array $objectIds, array $taxonomies, array $queryVars): array + { + if (!isset($queryVars['taxonomy'])) { + return $terms; + } + + $resource = $this->resourceRegistry->getRegisteredTaxonomy($queryVars['taxonomy'][0]); + + if(empty($resource)) { + return $terms; + } + + if( isset($queryVars['object_ids']) && !empty($queryVars['object_ids']) ) { + $queryVars['object_ids'] = array_map(function($objectId){ + + $objectResource = $this->getResourceFromObjectId($objectId); + + if( empty($objectResource) ) { + return null; + } + + return (int)str_replace($objectResource->resourceID, '', (string)absint($objectId)); + + }, $queryVars['object_ids']); + + array_filter($queryVars['object_ids']); + } + + $collection = TaxonomyResourceRequest::getCollection($resource, $queryVars); + + return $collection; + } + + private function getResourceFromTermId($termId):?object { + + if( $termId > -1 ) { + return null; + } + + $registeredTaxonomies = $this->resourceRegistry->getRegisteredTaxonomies(); + + if(empty($registeredTaxonomies)) { + return null; + } + + foreach($registeredTaxonomies as $registeredTaxonomy) { + $needle = (string)$registeredTaxonomy->resourceID; + $haystack = (string)absint($termId); + + if( str_starts_with($haystack, $needle) ) { + return $registeredTaxonomy; + } + } + + return null; + } + + private function getResourceFromObjectId(int $objectId):?object { + + if( $objectId > -1 ) { + return null; + } + + $registeredPostTypes = $this->resourceRegistry->getRegisteredPostTypes(); + + if(empty($registeredPostTypes)) { + return null; + } + + foreach($registeredPostTypes as $registeredPostType) { + $needle = (string)$registeredPostType->resourceID; + $haystack = (string)absint($objectId); + + if( str_starts_with($haystack, $needle) ) { + return $registeredPostType; + } + } + + return null; + } +} diff --git a/library/Content/ResourceFromApi/Taxonomy/TaxonomyRegistrar.php b/library/Content/ResourceFromApi/Taxonomy/TaxonomyRegistrar.php new file mode 100644 index 000000000..c85b9e12a --- /dev/null +++ b/library/Content/ResourceFromApi/Taxonomy/TaxonomyRegistrar.php @@ -0,0 +1,120 @@ +name = $name; + $this->arguments = $arguments; + + if (isset($arguments['object_type']) && is_array($arguments['object_type'])) { + $this->objectType = $arguments['object_type']; + } + } + + /** + * Registers the taxonomy. + * + * @return void + */ + public function register(): void + { + $this->prepareArguments(); + $this->registerTaxonomy(); + } + + /** + * Get the name of the taxonomy. + * + * @return string The name of the taxonomy. + */ + public function getName(): string + { + return $this->name; + } + + /** + * Get the arguments for registering a taxonomy. + * + * @return array The arguments for registering a taxonomy. + */ + public function getArguments(): array + { + return $this->arguments; + } + + /** + * Check if the taxonomy is registered. + * + * @return bool True if the taxonomy is registered, false otherwise. + */ + public function isRegistered(): bool + { + return $this->registered; + } + + /** + * Registers a taxonomy. + * + * @return void + */ + private function registerTaxonomy(): void + { + $success = register_taxonomy($this->getName(), $this->objectType, $this->getArguments()); + + if (is_a($success, WP_Taxonomy::class)) { + $this->registered = true; + } + } + + /** + * Prepares the arguments for the taxonomy registrar. + * + * @return void + */ + private function prepareArguments(): void + { + $preparedArguments = $this->arguments; + $preparedArguments = $this->prepareLabels($preparedArguments); + + $this->arguments = $preparedArguments; + } + + /** + * Prepare labels for a taxonomy based on the provided arguments. + * + * @param array $arguments The arguments to use for preparing the labels. + * @return array The prepared labels. + */ + private function prepareLabels(array $arguments): array + { + if (isset($arguments['labels_singular_name']) && !empty($arguments['labels_singular_name'])) { + $arguments['labels'] = ['singular_name' => $arguments['labels_singular_name']]; + } + + return $arguments; + } +} diff --git a/library/Content/ResourceFromApi/Taxonomy/TaxonomyResourceRequest.php b/library/Content/ResourceFromApi/Taxonomy/TaxonomyResourceRequest.php new file mode 100644 index 000000000..b4f4d45eb --- /dev/null +++ b/library/Content/ResourceFromApi/Taxonomy/TaxonomyResourceRequest.php @@ -0,0 +1,141 @@ + self::convertRestApiTermToWPTerm((object)$term, $resource), + $termsFromApi + ); + } + + public static function getSingle($id, object $resource): ?object + { + $url = self::getSingleUrl($id, $resource); + + if (empty($url)) { + return null; + } + + $termFromApi = RestRequestHelper::getFromApi($url); + + if (is_wp_error($termFromApi) || !is_array($termFromApi)) { + return null; + } + + return self::convertRestApiTermToWPTerm($termFromApi[0], $resource); + } + + public static function getCollectionHeaders(object $resource, ?array $queryArgs): array + { + $url = self::getCollectionUrl($resource, $queryArgs); + + if (empty($url)) { + return []; + } + + $headers = RestRequestHelper::getHeadersFromApi($url); + + if (is_wp_error($headers) || !is_array($headers)) { + return []; + } + + return $headers; + } + + public static function getMeta(int $id, string $metaKey, object $resource, bool $single = true) + { + $url = self::getSingleUrl($id, $resource); + $termFromApi = RestRequestHelper::getFromApi($url); + + if (isset($termFromApi->acf) && isset($termFromApi->acf->$metaKey)) { + if (is_array($termFromApi->acf->$metaKey)) { + return [$termFromApi->acf->$metaKey]; + } + + return $termFromApi->acf->$metaKey; + } + + if (isset($termFromApi->$metaKey)) { + if (is_array($termFromApi->$metaKey)) { + return [$termFromApi->$metaKey]; + } + + return $termFromApi->$metaKey; + } + + return null; + } + + private static function getSingleUrl($id, object $resource):?string { + + $collectionUrl = self::getCollectionUrl($resource); + + if( is_numeric($id) ) { + return trailingslashit($collectionUrl) . $id; + } + + return "{$collectionUrl}/?slug={$id}"; + } + + private static function getCollectionUrl(object $resource, ?array $queryArgs = null): ?string + { + $resourceUrl = get_field('taxonomy_source', $resource->resourceID); + + if (empty($resourceUrl)) { + return null; + } + + $restParams = !empty($queryArgs) + ? '?' . WPTermQueryToRestParamsConverter::convertToRestParamsString($queryArgs) + : ''; + + return $resourceUrl . $restParams; + } + + private static function getLocalID(int $id, object $resource): int + { + return -(int)"{$resource->resourceID}{$id}"; + } + + private static function convertRestApiTermToWPTerm(stdClass $termFromApi, object $resource): WP_Term + { + $localID = self::getLocalID($termFromApi->id, $resource); + $localTaxonomy = $resource->name; + + $term = new WP_Term(new \stdClass()); + $term->term_id = $localID; + $term->name = $termFromApi->name; + $term->slug = $termFromApi->slug; + $term->term_group = $termFromApi->term_group ?? 0; + $term->term_taxonomy_id = $termFromApi->taxonomy_id ?? 0; + $term->taxonomy = $localTaxonomy; + $term->description = $termFromApi->description ?? ''; + $term->parent = $termFromApi->parent ?? 0; + $term->count = $termFromApi->count ?? 0; + $term->filter = 'raw'; + + return apply_filters('Municipio/Content/ResourceFromApi/ConvertRestApiTermToWPTerm', $term, $termFromApi, $localTaxonomy); + } +} diff --git a/library/Content/ResourceFromApi/TypeRegistrarInterface.php b/library/Content/ResourceFromApi/TypeRegistrarInterface.php new file mode 100644 index 000000000..24edc5fc3 --- /dev/null +++ b/library/Content/ResourceFromApi/TypeRegistrarInterface.php @@ -0,0 +1,11 @@ +postMeta->{$fieldName} = $this->getFieldValue($metaKey); } - $this->appendAttachmentsData(); $this->appendImagesData(); $this->appendViewNotificationData(); $this->appendViewContactData(); @@ -50,7 +50,7 @@ private function getFieldName(string $fieldName): string private function getFieldValue($fieldName) { - return WP::getField($fieldName, $this->data['post']->id); + return WP::getField($fieldName, $this->data['post']->id, true); } private function getMetaKeys(): array @@ -100,27 +100,27 @@ private function appendViewNotificationData(): void private function appendViewContactData(): void { if (!isset($this->postMeta->contacts) || !post_type_exists(self::PERSON_POST_TYPE)) { + $this->data['contacts'] = null; return; } $personIds = array_map(function ($contact) { return $contact->person; - }, $this->postMeta->contacts); + }, $this->postMeta->contacts[0]); $persons = WP::getPosts(array('post_type' => self::PERSON_POST_TYPE, 'post__in' => $personIds, 'suppress_filters' => false)); $this->data['contacts'] = !empty($persons) ? array_map(function ($contact) use ($persons) { - $person = array_filter($persons, fn ($p) => $p->id === $contact->person); - $person = reset($person); + $personPosts = get_posts(['post_type' => self::PERSON_POST_TYPE, 'post__in' => [$contact->person], 'suppress_filters' => false]); - if (!$person) { + if( sizeof($personPosts) !== 1 ) { return null; } - $featuredMediaID = WP::getField('featured_media', $person->id); - $email = WP::getField('e-mail', $person->id); - $phone = WP::getField('phone-number', $person->id); + $featuredMediaID = WP::getField('featured_media', $personPosts[0]->ID); + $email = WP::getField('e-mail', $personPosts[0]->ID); + $phone = WP::getField('phone-number', $personPosts[0]->ID); $featuredMedia = $featuredMediaID ? WP::getPosts([ 'post_type' => self::MEDIA_POST_TYPE, @@ -133,10 +133,10 @@ private function appendViewContactData(): void 'professionalTitle' => $contact->professional_title ?? '', 'email' => $email, 'phone' => $phone, - 'name' => $person->postTitle + 'name' => $personPosts[0]->post_title ]; return $contact; - }, $this->postMeta->contacts) : null; + }, $this->postMeta->contacts[0]) : null; $this->data['contacts'] = array_filter($this->data['contacts'] ?? []); @@ -227,7 +227,7 @@ private function appendViewQuickFactsData(): void // Get usp taxonomy terms $uspTerms = get_terms([ 'taxonomy' => self::USP_TAXONOMY, - 'include' => $this->postMeta->usp, + 'include' => $this->postMeta->usp[0], 'orderby' => 'include', 'hide_empty' => false ]); @@ -379,22 +379,22 @@ private function appendViewVisitingData(): void $visitingData = array_map(fn($visitingAddress) => $visitingAddress->address, $visitingAddresses); $visitingData = array_map(function ($address) use(&$mapPins) { $mapsUrl = 'https://www.google.com/maps/search/?api=1&query=' . urlencode($address->address->address); - $street = $address->address->street_name ?? ''; - $streetNumber = $address->address->street_number ?? ''; - $postCode = $address->address->post_code ?? ''; - $city = $address->address->city ?? ''; + $street = $address[0]->address->street_name ?? ''; + $streetNumber = $address[0]->address->street_number ?? ''; + $postCode = $address[0]->address->post_code ?? ''; + $city = $address[0]->address->city ?? ''; $addressString = $street . ' ' . $streetNumber . ',
' . $postCode . ' ' . $city; $mapPinTooltip = ['title' => $this->data['post']->postTitle ?? null, 'excerpt' => $addressString]; $mapPins[] = [ - 'lat' => $address->address->lat, - 'lng' => $address->address->lng, + 'lat' => $address[0]->address->lat, + 'lng' => $address[0]->address->lng, 'tooltip' => $mapPinTooltip ]; return [ 'address' => $addressString, - 'description' => $address->description ?? null, + 'description' => $address[0]->description ?? null, 'mapsLink' => ['href' => $mapsUrl, 'text' => __('Find directions', 'municipio')] ]; }, $visitingAddresses); @@ -427,10 +427,11 @@ private function getMapStartPosition(array $mapPins): array private function appendViewPagesData(): void { if( !post_type_exists(self::PAGE_POST_TYPE) ) { + $this->data['pages'] = null; return; } - $pageIds = $this->postMeta->pages; + $pageIds = $this->postMeta->pages[0] ?? []; if (!isset($pageIds) || empty($pageIds)) { $this->data['pages'] = null; @@ -482,49 +483,22 @@ private function appendSocialMediaLinksData(): void $this->data['socialMediaLinks'] = $socialMediaLinks; } - private function appendAttachmentsData(): void + private function appendImagesData(): void { - if( !post_type_exists(self::MEDIA_POST_TYPE) ) { - return; - } - - $attachmentIds = array_map(fn ($attachment) => $attachment->image->id, array_merge( - $this->postMeta->facadeImages ?: [], - $this->postMeta->gallery ?: [] - )); - - $attachments = WP::getPosts([ + $facadeAttachmentIds = array_map(fn($facadeImage) => $facadeImage->image->id ,$this->postMeta->facadeImages ?? [] ); + $facadeAttachments = !empty($facadeAttachmentIds) ? WP::getPosts([ 'post_type' => self::MEDIA_POST_TYPE, - 'post__in' => $attachmentIds, + 'post__in' => $facadeAttachmentIds, 'suppress_filters' => false - ]); - - $attachmentsById = []; - foreach ($attachments as $attachment) { - - $attachmentsById[$attachment->id] = $attachment; - } - - $this->postMeta->attachments = $attachmentsById; - } - - private function appendImagesData(): void - { + ]) : []; - if (!isset($this->postMeta->attachments)) { - return; - } - - $facadeAttachments = array_filter($this->postMeta->attachments, function ($attachmentId) { - $facadeImageIds = array_map(fn ($attachment) => $attachment->image->id, $this->postMeta->facadeImages ?: []); - return in_array($attachmentId, $facadeImageIds ?: []); - }, ARRAY_FILTER_USE_KEY); - - $galleryAttachments = array_filter($this->postMeta->attachments, function ($attachmentId) { - $galleryImageIds = array_map(fn ($attachment) => $attachment->image->id, $this->postMeta->gallery ?: []); - return in_array($attachmentId, $galleryImageIds ?: []); - }, ARRAY_FILTER_USE_KEY); + $galleryAttachmentIds = array_map(fn($galleryImage) => $galleryImage->image->id ,$this->postMeta->gallery ?? [] ); + $galleryAttachments = !empty($galleryAttachmentIds) ? WP::getPosts([ + 'post_type' => self::MEDIA_POST_TYPE, + 'post__in' => $galleryAttachmentIds, + 'suppress_filters' => false + ]) : []; $this->data['facadeSliderItems'] = !empty($facadeAttachments) ? array_map([$this, 'attachmentToSliderItem'], $facadeAttachments) @@ -534,7 +508,6 @@ private function appendImagesData(): void ? array_map([$this, 'attachmentToSliderItem'], $galleryAttachments) : null; - $this->data['video'] = (empty($this->data['gallerySliderItems']) && !empty($this->postMeta->video)) ? $this->postMeta->video diff --git a/library/Controller/SchoolArchiveContentType.php b/library/Controller/SchoolArchiveContentType.php index 473b2d888..92dabaffe 100644 --- a/library/Controller/SchoolArchiveContentType.php +++ b/library/Controller/SchoolArchiveContentType.php @@ -26,7 +26,7 @@ public function modifyArchiveListAppearance($data) } $posts = $data['posts']['items']; - $taxonomies = array_filter(['area'], 'taxonomy_exists'); + $taxonomies = array_filter(['school-area'], 'taxonomy_exists'); $postType = get_post_type(); $postTypeObject = get_post_type_object($postType); $postTypeLabel = $postTypeObject->label; @@ -58,7 +58,7 @@ public function modifyArchiveListAppearance($data) private function getTermName(string $taxonomy, int $postId): string { - $terms = WP::getPostTerms([$taxonomy], $postId); + $terms = get_terms(['object_ids' => [$postId], 'taxonomy' => $taxonomy]); return !empty($terms) ? $terms[0]->name : ''; } diff --git a/library/Helper/WP.Test.php b/library/Helper/WP.Test.php new file mode 100644 index 000000000..bdcd80cbe --- /dev/null +++ b/library/Helper/WP.Test.php @@ -0,0 +1,34 @@ +factory()->term->create_and_get(['taxonomy' => 'category']); + $post = $this->factory()->post->create_and_get(); + wp_set_post_terms($post->ID, [$term->term_id], 'category'); + + // Act + $result = WP::getTerms(['taxonomy' => 'category'], $post->ID); + + // Assert + $this->assertEquals($term->term_id, $result[0]->term_id); + + // Cleanup + wp_delete_term($term->term_id, 'category'); + wp_delete_post($post->ID, true); + } + + public function testGetTermsReturnsEmptyArrayWhenNoTerms() + { + // Arrange, Act + $terms = WP::getTerms(['taxonomy' => 'nonexistent_taxonomy']); + // Assert + $this->assertEmpty($terms); + } +} diff --git a/views/v3/content-type-school.blade.php b/views/v3/content-type-school.blade.php index de5b5b6ae..ce9824bc6 100644 --- a/views/v3/content-type-school.blade.php +++ b/views/v3/content-type-school.blade.php @@ -139,11 +139,13 @@ {{$visitingAddress['description']}}
@endif {!!$visitingAddress['address']!!} - @link([ - 'href' => $visitingAddress['mapsLink']['href'] + @button([ + 'text' => $visitingAddress['mapsLink']['text'], + 'href' => $visitingAddress['mapsLink']['href'], + 'color' => 'primary', + 'style' => 'basic', ]) - {{$visitingAddress['mapsLink']['text']}} - @endlink + @endbutton @endtypography @endforeach