Taak 127-A — Drupal-patch voor de kloonbron
===========================================

Bestand op de server:
  sites/all/modules/custom/custom.mijn_aanmeldingen.inc
  (volledig pad productie: /data/disk/o1/static/uitgaanskrant/sites/all/
   modules/custom/custom.mijn_aanmeldingen.inc)

TWEE INGREPEN, daarna `drush @uitgaanskrant.com cc all`:

1) REGEL 125 in _custom_aanm_veldkaart(), blok 'activity':
       'entree'      => NULL,
   wordt
       'entree'      => 'field_act_entree',

   Waarom: _custom_stadsactiviteit_create() schrijft wel degelijk naar
   field_act_entree (door Bob toegevoegd 2026-08-26, zelfde vocabulary als
   field_goo_entree). Zonder deze regel gaat het entree-type verloren bij
   het klonen van een activiteit. Bewijs: node 222818 heeft
   field_act_entree = 36197 en dat kwam niet mee in de respons.

2) REGELS 240 t/m 313 (de regel `/**` van het A2-docblock t/m de laatste `}`
   van het bestand) vervangen door ALLES hieronder, vanaf de markering.

Getest op productie 2026-09-20 (read-only, via drush php-script; het bestand
zelf is niet gewijzigd). Uitkomsten staan in TASKS.md taak 127-A.

Let op: `file_create_url()` geeft onder drush `http://` omdat er geen
request-context is. Via een echte HTTP-request levert Drupal `https://` --
niet "repareren", wel bij de eerste test vanuit de app controleren.

⬇ PLAK VANAF HIER ⬇

/**
 * Alle bestands-URL's van een (multi-value) bestandsveld.
 *
 * Tegenhanger van _custom_aanm_bestand_url() voor meerdere waarden.
 */
function _custom_aanm_bestand_urls($node, $veld) {
  $uit = array();
  if (empty($veld)) {
    return $uit;
  }
  $items = field_get_items('node', $node, $veld);
  if (empty($items) || !is_array($items)) {
    return $uit;
  }
  foreach ($items as $item) {
    if (is_array($item) && !empty($item['uri'])) {
      $uit[] = file_create_url($item['uri']);
    }
  }
  return $uit;
}

/**
 * Uitgeklapte keten provincie|gemeente|plaats voor een town-tid.
 *
 * Zelfde niveaubepaling als _custom_mijn_stadsrechten_service():
 * count(taxonomy_get_parents_all()) geeft 1 = provincie, 2 = gemeente,
 * 3 = plaats. De app splitst 'keten' met dezelfde custom functions als
 * bij de stadsrechten-cascade, dus het scheidingsteken moet '|' blijven.
 */
function _custom_aanm_keten($tid) {
  $leeg = array(
    'provincie_tid' => NULL,
    'gemeente_tid'  => NULL,
    'plaats_tid'    => NULL,
    'keten'         => '||',
  );
  if (empty($tid)) {
    return $leeg;
  }
  $ouders = taxonomy_get_parents_all((int) $tid);
  if (empty($ouders)) {
    return $leeg;
  }
  // taxonomy_get_parents_all levert kind -> ... -> wortel; omdraaien.
  $pad = array_reverse($ouders);
  $uit = $leeg;
  if (isset($pad[0])) {
    $uit['provincie_tid'] = (string) $pad[0]->tid;
  }
  if (isset($pad[1])) {
    $uit['gemeente_tid'] = (string) $pad[1]->tid;
  }
  if (isset($pad[2])) {
    $uit['plaats_tid'] = (string) $pad[2]->tid;
  }
  $uit['keten'] = implode('|', array(
    $uit['provincie_tid'] !== NULL ? $uit['provincie_tid'] : '',
    $uit['gemeente_tid'] !== NULL ? $uit['gemeente_tid'] : '',
    $uit['plaats_tid'] !== NULL ? $uit['plaats_tid'] : '',
  ));
  return $uit;
}

/**
 * A2 — kloonbron: de RAUWE waarden van één eigen aanmelding.
 *
 * GET /nl/flutterdrup/aanmelding_kloonbron.json?nid=X
 *
 * Geeft tids en fids terug, niet de weergavewaarden — precies de sleutels
 * die evenementen/create en stadsactiviteiten/create verwachten. Daarnaast
 * logo_url/fotos_urls voor de preview op de aanmaakpagina, en bij een
 * activiteit de uitgeklapte plaatsketen voor de cascade-dropdowns.
 */
function _custom_aanmelding_kloonbron() {
  global $user;

  if (empty($user->uid)) {
    return services_error('Niet ingelogd.', 401);
  }

  $nid = isset($_GET['nid']) ? (int) $_GET['nid'] : 0;
  if ($nid < 1) {
    return services_error('Parameter nid ontbreekt.', 400);
  }

  $node = node_load($nid);
  if (!$node) {
    return services_error('Aanmelding niet gevonden.', 404);
  }
  if (!in_array($node->type, array('go_out_event', 'activity'), TRUE)) {
    return services_error('Dit is geen aanmelding.', 400);
  }
  // Eigenaarscheck: zonder dit leest iemand andermans gegevens uit.
  if ((int) $node->uid !== (int) $user->uid) {
    return services_error('Geen toegang tot deze aanmelding.', 403);
  }

  $v = _custom_aanm_veldkaart($node->type);

  $titel = !empty($v['titel']) ? _custom_aanm_item($node, $v['titel']) : NULL;
  if (empty($titel)) {
    $titel = $node->title;
  }

  // Gedeelde velden. De datumvelden komen bewust NIET mee: je kloont juist
  // om hetzelfde op een nieuwe datum te zetten.
  $uit = array(
    'nid'                => (int) $node->nid,
    'type'               => $node->type,
    'titel'              => $titel,
    'omschrijving'       => _custom_aanm_item($node, 'body', 'value'),
    'entree_prijs'       => _custom_aanm_item($node, $v['prijs'], 'value'),
    'toelichting_entree' => _custom_aanm_item($node, $v['toelichting'], 'value'),
    'website_url'        => _custom_aanm_item($node, $v['website'], 'url'),
    'categorie_tids'     => _custom_aanm_lijst($node, $v['categorie'], 'tid'),
    'logo_fid'           => _custom_aanm_item($node, $v['logo'], 'fid'),
    'fotos_fids'         => _custom_aanm_lijst($node, $v['fotos'], 'fid'),
    // Voor de preview op de aanmaakpagina; de create-actie gebruikt de fids.
    'logo_url'           => _custom_aanm_bestand_url($node, $v['logo']),
    'fotos_urls'         => _custom_aanm_bestand_urls($node, $v['fotos']),
    // Beide types hebben een entree-veld (field_goo_entree resp.
    // field_act_entree, zelfde vocabulary) — zie _custom_aanm_veldkaart().
    'entree_tid'         => !empty($v['entree'])
      ? _custom_aanm_item($node, $v['entree'], 'tid')
      : NULL,
  );

  if ($node->type === 'go_out_event') {
    $uit['horecagelegenheid_nid'] = _custom_aanm_item($node, $v['horeca'], 'target_id');
    $uit['tickets_url']           = _custom_aanm_item($node, $v['tickets'], 'url');
  }
  else {
    $plaats_tid = _custom_aanm_item($node, $v['plaats'], 'tid');
    $uit['plaats_tid'] = $plaats_tid;
    // Uitgeklapt, zodat de app de drie cascade-dropdowns kan voorvullen.
    $uit += _custom_aanm_keten($plaats_tid);
    $uit['organisator'] = _custom_aanm_item($node, $v['organisator'], 'value');
    $uit['contact']     = _custom_aanm_item($node, $v['contact'], 'value');

    $adres = field_get_items('node', $node, $v['adres']);
    if (!empty($adres[0]) && is_array($adres[0])) {
      $uit['adres_straat']   = isset($adres[0]['thoroughfare']) ? $adres[0]['thoroughfare'] : NULL;
      $uit['adres_postcode'] = isset($adres[0]['postal_code']) ? $adres[0]['postal_code'] : NULL;
      $uit['adres_plaats']   = isset($adres[0]['locality']) ? $adres[0]['locality'] : NULL;
    }
  }

  return $uit;
}
