/** * WPML compatibility functions * * @global array $duplicated_posts Array to store the posts being duplicated. * * @package Yoast\WP\Duplicate_Post * @since 3.2 */ add_action( 'admin_init', 'duplicate_post_wpml_init' ); /** * Add handlers for WPML compatibility. */ function duplicate_post_wpml_init() { if ( defined( 'ICL_SITEPRESS_VERSION' ) ) { add_action( 'dp_duplicate_page', 'duplicate_post_wpml_copy_translations', 10, 3 ); add_action( 'dp_duplicate_post', 'duplicate_post_wpml_copy_translations', 10, 3 ); add_action( 'shutdown', 'duplicate_wpml_string_packages', 11 ); } } global $duplicated_posts; // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: Renaming a global variable is a BC break. $duplicated_posts = []; /** * Copy post translations. * * @global SitePress $sitepress Instance of the Main WPML class. * @global array $duplicated_posts Array of duplicated posts. * * @param int $post_id ID of the copy. * @param WP_Post $post Original post object. * @param string $status Status of the new post. */ function duplicate_post_wpml_copy_translations( $post_id, $post, $status = '' ) { global $sitepress; global $duplicated_posts; remove_action( 'dp_duplicate_page', 'duplicate_post_wpml_copy_translations', 10 ); remove_action( 'dp_duplicate_post', 'duplicate_post_wpml_copy_translations', 10 ); $current_language = $sitepress->get_current_language(); $trid = $sitepress->get_element_trid( $post->ID ); if ( ! empty( $trid ) ) { $translations = $sitepress->get_element_translations( $trid ); $new_trid = $sitepress->get_element_trid( $post_id ); foreach ( $translations as $code => $details ) { if ( $code !== $current_language ) { if ( $details->element_id ) { $translation = get_post( $details->element_id ); if ( ! $translation ) { continue; } $new_post_id = duplicate_post_create_duplicate( $translation, $status ); if ( ! is_wp_error( $new_post_id ) ) { $sitepress->set_element_language_details( $new_post_id, 'post_' . $translation->post_type, $new_trid, $code, $current_language ); } } } } // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: see above. $duplicated_posts[ $post->ID ] = $post_id; } } /** * Duplicate string packages. * * @global array() $duplicated_posts Array of duplicated posts. */ function duplicate_wpml_string_packages() { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: renaming the function would be a BC-break. global $duplicated_posts; foreach ( $duplicated_posts as $original_post_id => $duplicate_post_id ) { // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. $original_string_packages = apply_filters( 'wpml_st_get_post_string_packages', false, $original_post_id ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. $new_string_packages = apply_filters( 'wpml_st_get_post_string_packages', false, $duplicate_post_id ); if ( is_array( $original_string_packages ) ) { foreach ( $original_string_packages as $original_string_package ) { $translated_original_strings = $original_string_package->get_translated_strings( [] ); foreach ( $new_string_packages as $new_string_package ) { $cache = new WPML_WP_Cache( 'WPML_Package' ); $cache->flush_group_cache(); $new_strings = $new_string_package->get_package_strings(); foreach ( $new_strings as $new_string ) { if ( isset( $translated_original_strings[ $new_string->name ] ) ) { foreach ( $translated_original_strings[ $new_string->name ] as $language => $translated_string ) { do_action( // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals -- Reason: using WPML native filter. 'wpml_add_string_translation', $new_string->id, $language, $translated_string['value'], $translated_string['status'] ); } } } } } } } } display_fieldsの穴埋め(既存モデルバージョン) – Raqqa

display_fieldsの穴埋め(既存モデルバージョン)

既存モデル(例:account.paymentaccount.move)でもir_field_src の many2one 1行(種)から

  • by_model(モデル→field配列)
  • aliases(orders/lines みたいな2モデルalias)
  • flat(alias.field の修飾名配列)

を生成して、portal_view_common.display_fields に入るかを 検証できるSQLを出します。

ここではあなたが貼ってくれた例の

  • id = 5024
  • account.payment.move_id many2one → account.move

を使います。


1) まず payload を “生成して見るだけ”(SELECT)

(既存モデルでもデータが揃っているかを確認する用途)

WITH seed AS (
  SELECT
    id AS seed_id,
    relation AS header_model,  -- parent側: account.move
    model    AS line_model     -- child側: account.payment
  FROM public.ir_field_src
  WHERE id = 5024
),
by_model AS (
  SELECT jsonb_object_agg(model, fields_arr) AS v
  FROM (
    SELECT
      m.model,
      to_jsonb(array_agg(f.field_name ORDER BY f.field_name)) AS fields_arr
    FROM (
      SELECT header_model AS model FROM seed
      UNION ALL
      SELECT line_model   AS model FROM seed
    ) m
    JOIN public.ir_field_src f ON f.model = m.model
    GROUP BY m.model
  ) t
),
aliases AS (
  SELECT jsonb_build_object(
    'header', (SELECT header_model FROM seed),
    'line',   (SELECT line_model   FROM seed)
  ) AS v
),
flat AS (
  SELECT to_jsonb(array_agg(qualified ORDER BY qualified)) AS v
  FROM (
    SELECT 'header.' || f.field_name AS qualified
    FROM public.ir_field_src f
    JOIN seed s ON f.model = s.header_model
    UNION ALL
    SELECT 'line.' || f.field_name
    FROM public.ir_field_src f
    JOIN seed s ON f.model = s.line_model
  ) q
),
payload AS (
  SELECT jsonb_build_object(
    'by_model', (SELECT v FROM by_model),
    'aliases',  (SELECT v FROM aliases),
    'flat',     (SELECT v FROM flat),
    'tag',      'E2E_VERIFY_EXISTING',
    'scope',    'account',
    'seed_ir_field_src_id', (SELECT seed_id FROM seed)
  ) AS v
)
SELECT
  (SELECT header_model FROM seed) AS header_model,
  (SELECT line_model   FROM seed) AS line_model,
  v AS display_fields_payload
FROM payload;

✅ これで by_model が 2キー(account.moveaccount.payment)になっていて、配列が埋まっていればOKです。


2) 検証用に portal_view_common を “仮で1行” 作る(INSERT)

既存モデルでも view_common は必要なので、検証用の action_xmlid を作ります。

INSERT INTO public.portal_view_common
  (action_xmlid, action_name, model_label, model_tech, model_table, view_types, primary_view_type, display_fields)
VALUES
  (
    'e2e.verify.account_payment_move',
    'E2E Verify: account.payment ↔ account.move',
    'E2E Verify',
    'account.payment',
    'account_payment',
    '{form}',
    'form',
    '[]'::jsonb
  )
ON CONFLICT (action_xmlid) DO NOTHING;

3) その行に display_fields を流し込む(UPDATE + RETURNING)

(ここが “埋まるか” の最終検証)

WITH seed AS (
  SELECT
    id AS seed_id,
    relation AS header_model,
    model    AS line_model
  FROM public.ir_field_src
  WHERE id = 5024
),
by_model AS (
  SELECT jsonb_object_agg(model, fields_arr) AS v
  FROM (
    SELECT
      m.model,
      to_jsonb(array_agg(f.field_name ORDER BY f.field_name)) AS fields_arr
    FROM (
      SELECT header_model AS model FROM seed
      UNION ALL
      SELECT line_model   AS model FROM seed
    ) m
    JOIN public.ir_field_src f ON f.model = m.model
    GROUP BY m.model
  ) t
),
aliases AS (
  SELECT jsonb_build_object(
    'header', (SELECT header_model FROM seed),
    'line',   (SELECT line_model   FROM seed)
  ) AS v
),
flat AS (
  SELECT to_jsonb(array_agg(qualified ORDER BY qualified)) AS v
  FROM (
    SELECT 'header.' || f.field_name AS qualified
    FROM public.ir_field_src f
    JOIN seed s ON f.model = s.header_model
    UNION ALL
    SELECT 'line.' || f.field_name
    FROM public.ir_field_src f
    JOIN seed s ON f.model = s.line_model
  ) q
),
payload AS (
  SELECT jsonb_build_object(
    'by_model', (SELECT v FROM by_model),
    'aliases',  (SELECT v FROM aliases),
    'flat',     (SELECT v FROM flat),
    'tag',      'E2E_VERIFY_EXISTING',
    'scope',    'account',
    'seed_ir_field_src_id', (SELECT seed_id FROM seed)
  ) AS v
)
UPDATE public.portal_view_common pvc
SET display_fields = payload.v,
    updated_at = now()
FROM payload
WHERE pvc.action_xmlid = 'e2e.verify.account_payment_move'
RETURNING pvc.action_xmlid, jsonb_typeof(pvc.display_fields) AS display_fields_type, pvc.display_fields;

RETURNING で 1行返って、display_fields_type = 'object' なら成功です。


4) 片付け(検証用行だけ消す)

DELETE FROM public.portal_view_common
WHERE action_xmlid = 'e2e.verify.account_payment_move';

Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です