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; }