maximus87

event industrie

Oct 20th, 2025
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 24.81 KB | None | 0 0
  1. /**
  2. * Minasa XML Export (events + schedules + locations + organizers + dataProviders)
  3. * Optimized:
  4. * - Eligible event IDs are computed once and cached (transient + in-request memo)
  5. * - Generator loops IDs directly (no heavy WP_Query object loop)
  6. * - Uses site timezone, fixes date-only noon nudge, aligns schedules to <duration>
  7. * - Excludes ACF true/false remove_from_export
  8. */
  9.  
  10. if (!defined('ABSPATH')) exit;
  11.  
  12. /*------------------------------------------------------------------------------
  13. | CRON: daily generation + only-when-needed
  14. ------------------------------------------------------------------------------*/
  15. add_action('init', function () {
  16. if (!wp_next_scheduled('generate_azizi_xml_daily')) {
  17. wp_schedule_event(time(), 'daily', 'generate_azizi_xml_daily');
  18. }
  19. });
  20. add_action('generate_azizi_xml_daily', 'maybe_generate_azizi_xml');
  21.  
  22. function minasa_get_latest_event_modified_gmt(): int {
  23. $q = new WP_Query([
  24. 'post_type' => 'offbeat-event',
  25. 'post_status' => 'publish',
  26. 'posts_per_page' => 1,
  27. 'orderby' => 'modified',
  28. 'order' => 'DESC',
  29. 'fields' => 'ids',
  30. 'no_found_rows' => true,
  31. 'update_post_term_cache' => false,
  32. 'update_post_meta_cache' => false,
  33. ]);
  34. if (!empty($q->posts)) {
  35. return (int) get_post_modified_time('U', true, $q->posts[0]); // GMT epoch
  36. }
  37. return 0;
  38. }
  39.  
  40. function maybe_generate_azizi_xml() {
  41. $file_path = ABSPATH . 'azizi.xml';
  42. $last_run = file_exists($file_path) ? filemtime($file_path) : 0;
  43. $latest_mod = minasa_get_latest_event_modified_gmt();
  44.  
  45. if ($latest_mod > $last_run) {
  46. generate_azizi_xml($file_path);
  47. }
  48. }
  49.  
  50. /*------------------------------------------------------------------------------
  51. | CACHED ID LIST: compute once, cache, then reuse
  52. ------------------------------------------------------------------------------*/
  53. function minasa_get_export_event_ids(bool $force = false): array {
  54. static $memo = null; // in-request memoization
  55.  
  56. if (!$force && is_array($memo)) {
  57. return $memo;
  58. }
  59.  
  60. $todayYmd = date('Ymd'); // local date; matches how your ACF Ymd is compared elsewhere
  61. $latest_mod = minasa_get_latest_event_modified_gmt();
  62.  
  63. // Transient key includes the day + latest modified GMT → auto-invalidates on change
  64. $t_key = "minasa_export_ids_{$todayYmd}_{$latest_mod}";
  65. if (!$force) {
  66. $cached = get_transient($t_key);
  67. if (is_array($cached)) {
  68. return $memo = $cached;
  69. }
  70. }
  71.  
  72. // Build a lean ID-only query that excludes remove_from_export = true
  73. $args = [
  74. 'post_type' => 'offbeat-event',
  75. 'post_status' => 'publish',
  76. 'posts_per_page' => -1,
  77. 'fields' => 'ids',
  78. 'no_found_rows' => true,
  79. 'update_post_term_cache' => false,
  80. 'update_post_meta_cache' => false,
  81. 'meta_query' => [
  82. 'relation' => 'AND',
  83. // date-window inclusion
  84. [
  85. 'relation' => 'OR',
  86. [
  87. 'key' => 'edgtf_event_end_date',
  88. 'value' => $todayYmd,
  89. 'compare' => '>=',
  90. 'type' => 'NUMERIC',
  91. ],
  92. [
  93. 'relation' => 'AND',
  94. [
  95. 'key' => 'edgtf_event_end_date',
  96. 'value' => '',
  97. 'compare' => '=',
  98. ],
  99. [
  100. 'key' => 'edgtf_event_start_date',
  101. 'value' => $todayYmd,
  102. 'compare' => '>=',
  103. 'type' => 'NUMERIC',
  104. ],
  105. ],
  106. ],
  107. // exclude remove_from_export = true
  108. [
  109. 'relation' => 'OR',
  110. [
  111. 'key' => 'remove_from_export',
  112. 'compare' => 'NOT EXISTS',
  113. ],
  114. [
  115. 'key' => 'remove_from_export',
  116. 'value' => '1',
  117. 'compare' => '!=',
  118. ],
  119. ],
  120. ],
  121. ];
  122. $q = new WP_Query($args);
  123. $ids = $q->posts ?: [];
  124.  
  125. // Cache (24h TTL; key auto-changes when content changes, so we don’t need to delete)
  126. set_transient($t_key, $ids, DAY_IN_SECONDS);
  127. return $memo = $ids;
  128. }
  129.  
  130. // Optional: purge helper if you want to invalidate eagerly on edits.
  131. function minasa_purge_export_id_cache(): void {
  132. // No-op: keys are content-addressed. You can still delete all 'minasa_export_ids_*' if you track last key.
  133. }
  134. // Example eager purge on edits to relevant meta (optional)
  135. add_action('updated_post_meta', function($meta_id, $post_id, $meta_key) {
  136. if (get_post_type($post_id) !== 'offbeat-event') return;
  137. if (in_array($meta_key, ['edgtf_event_start_date','edgtf_event_end_date','remove_from_export'], true)) {
  138. minasa_purge_export_id_cache();
  139. }
  140. }, 10, 3);
  141.  
  142. /*------------------------------------------------------------------------------
  143. | Helpers: date parsing + interval building + organizers/locations payloads
  144. ------------------------------------------------------------------------------*/
  145.  
  146. function minasa_parse_date_v2($date_str, DateTimeZone $tz = null) {
  147. $date_str = trim((string) $date_str);
  148. if ($date_str === '') return null;
  149. $tz = $tz ?: wp_timezone();
  150.  
  151. $norm = str_replace(['.', '/'], '-', $date_str);
  152. $candidates = array_unique([$date_str, $norm]);
  153.  
  154. $formats = ['Ymd','Y-m-d','Y/m/d','d.m.Y','d/m/Y','m/d/Y','d-m-Y','m-d-Y'];
  155. foreach ($candidates as $cand) {
  156. foreach ($formats as $fmt) {
  157. $dt = DateTime::createFromFormat($fmt, $cand, $tz);
  158. if ($dt instanceof DateTime) {
  159. $err = DateTime::getLastErrors();
  160. if (($err['warning_count'] ?? 0) === 0 && ($err['error_count'] ?? 0) === 0) {
  161. $dt->setTime(0, 0, 0);
  162. return $dt;
  163. }
  164. }
  165. }
  166. }
  167. $ts = strtotime($norm);
  168. if ($ts !== false) {
  169. $dt = new DateTime('@' . $ts);
  170. $dt->setTimezone($tz);
  171. $dt->setTime(0, 0, 0);
  172. return $dt;
  173. }
  174. error_log("[Minasa] Failed to parse date '{$date_str}'");
  175. return null;
  176. }
  177.  
  178. function minasa_build_interval_v2($start_date, $end_date, $start_time, $end_time) {
  179. $tz = wp_timezone();
  180.  
  181. $sd = minasa_parse_date_v2($start_date, $tz);
  182. if (!$sd) return [null, null];
  183.  
  184. $start_time = trim((string)$start_time);
  185. if ($start_time === '') {
  186. $sd->setTime(12, 0, 0); // noon to avoid UTC rollback on date-only
  187. } else {
  188. [$sh, $sm] = array_pad(explode(':', $start_time, 2), 2, '00');
  189. $sd->setTime((int)$sh, (int)$sm, 0);
  190. }
  191.  
  192. if ($end_date || $end_time) {
  193. $ed = minasa_parse_date_v2($end_date ?: $start_date, $tz) ?: clone $sd;
  194. $end_time = trim((string)$end_time);
  195. if ($end_time === '') {
  196. $ed = clone $sd;
  197. $ed->add(new DateInterval('PT3H'));
  198. } else {
  199. [$eh, $em] = array_pad(explode(':', $end_time, 2), 2, '00');
  200. $ed->setTime((int)$eh, (int)$em, 0);
  201. if ($ed < $sd) {
  202. $ed = clone $sd;
  203. $ed->add(new DateInterval('PT1H'));
  204. }
  205. }
  206. } else {
  207. $ed = clone $sd;
  208. $ed->add(new DateInterval('PT3H'));
  209. }
  210.  
  211. return [$sd, $ed];
  212. }
  213.  
  214. function collect_location_term_payload($term, $data_provider_uuid) {
  215. $tid = (int) $term->term_id;
  216. $organizer = resolve_default_organizer_record($data_provider_uuid);
  217.  
  218. return [
  219. 'organizerUuid7' => $organizer['uuid'],
  220. 'dataProviderUuid7' => $data_provider_uuid,
  221. 'created' => current_time(DATE_ATOM),
  222. 'modified' => current_time(DATE_ATOM),
  223. 'providerReference' => ['id' => (string)$tid, 'url' => get_term_link($term)],
  224. 'imageUrl' => '',
  225. 'title' => $term->name,
  226. 'street' => (string) get_field('street', "event_location_{$tid}"),
  227. 'zip' => (string) get_field('zip', "event_location_{$tid}"),
  228. 'city' => (string) get_field('city', "event_location_{$tid}"),
  229. 'country' => 'CH',
  230. 'phone' => (string) get_field('phone', "event_location_{$tid}"),
  231. 'email' => (string) get_field('email', "event_location_{$tid}"),
  232. 'url' => (string) get_field('web_url', "event_location_{$tid}"),
  233. ];
  234. }
  235.  
  236. function resolve_organizer_for_post($post_id, $data_provider_uuid) {
  237. $name = trim((string) get_field('organizer_name', $post_id));
  238. $city = trim((string) get_field('organizer_city', $post_id));
  239. $zip = trim((string) get_field('organizer_zip', $post_id));
  240. $email = trim((string) get_field('organizer_email', $post_id));
  241. $url = trim((string) get_field('organizer_url', $post_id));
  242.  
  243. if ($name !== '') {
  244. $key = sanitize_title($name);
  245. $uuid = wp_generate_uuid4();
  246. return [
  247. 'key' => $key,
  248. 'uuid' => $uuid,
  249. 'data' => [
  250. 'dataProviderUuid7' => $data_provider_uuid,
  251. 'created' => current_time(DATE_ATOM),
  252. 'modified' => current_time(DATE_ATOM),
  253. 'imageUrl' => '',
  254. 'providerReference' => ['id' => $key, 'url' => home_url('/organizer/' . $key)],
  255. 'title' => $name,
  256. 'zip' => $zip,
  257. 'city' => $city,
  258. 'country' => 'CH',
  259. 'email' => $email,
  260. 'url' => $url,
  261. ],
  262. ];
  263. }
  264. return resolve_default_organizer_record($data_provider_uuid);
  265. }
  266.  
  267. function resolve_default_organizer_record($data_provider_uuid) {
  268. $site_name = get_bloginfo('name') ?: 'Site Organizer';
  269. $key = sanitize_title($site_name);
  270. $seed = md5(home_url() . '|organizer|' . $key);
  271. $uuid = sprintf('%08s-%04s-%04s-%04s-%12s',
  272. substr($seed, 0, 8), substr($seed, 8, 4), substr($seed, 12, 4),
  273. substr($seed, 16, 4), substr($seed, 20, 12)
  274. );
  275. return [
  276. 'key' => $key,
  277. 'uuid' => $uuid,
  278. 'data' => [
  279. 'dataProviderUuid7' => $data_provider_uuid,
  280. 'created' => current_time(DATE_ATOM),
  281. 'modified' => current_time(DATE_ATOM),
  282. 'imageUrl' => '',
  283. 'providerReference' => ['id' => 'organizer-' . $key, 'url' => home_url()],
  284. 'title' => $site_name,
  285. 'zip' => '',
  286. 'city' => '',
  287. 'country' => 'CH',
  288. 'email' => get_option('admin_email'),
  289. 'url' => home_url(),
  290. ],
  291. ];
  292. }
  293.  
  294. /*------------------------------------------------------------------------------
  295. | Generator: loops cached IDs, primes caches, writes XML
  296. ------------------------------------------------------------------------------*/
  297. function generate_azizi_xml($file_path) {
  298. $site_tz = wp_timezone();
  299.  
  300. // Data provider identity
  301. $data_provider_uuid = apply_filters('minasa_dataprovider_uuid7', '73308c2c-dbf4-710d-b896-19cc49673998');
  302. $data_provider_name = apply_filters('minasa_dataprovider_name', preg_replace('~https?://~', '', home_url()));
  303.  
  304. // Get and cache eligible event IDs once
  305. $event_ids = minasa_get_export_event_ids();
  306.  
  307. // Prime caches to reduce DB hits in the loop
  308. if ($event_ids) {
  309. // Prime post object + meta (private core function but stable), then term cache
  310. if (function_exists('_prime_post_caches')) {
  311. _prime_post_caches($event_ids, false, true);
  312. } else {
  313. update_meta_cache('post', $event_ids);
  314. }
  315. update_object_term_cache($event_ids, 'offbeat-event');
  316. }
  317.  
  318. $writer = new XMLWriter();
  319. $writer->openURI($file_path);
  320. $writer->startDocument('1.0', 'UTF-8');
  321. $writer->setIndent(true);
  322. $writer->setIndentString(' ');
  323.  
  324. $writer->startElement('minasa');
  325. $writer->writeAttribute('xsi:schemaLocation', 'https://minasa-demo.ch/services/export/azizi/1.0?schema');
  326. $writer->writeAttribute('xmlns:xsi', 'http://www.w3.org/2001/XMLSchema-instance');
  327. $writer->writeAttribute('xmlns', 'https://minasa.ch/schema/v1');
  328.  
  329. // Maps for referenced entities
  330. $location_map = [];
  331. $organizer_map = [];
  332. $touched_locations = [];
  333. $touched_organizers = [];
  334.  
  335. /*----------------------------------
  336. | <events>
  337. ----------------------------------*/
  338. $writer->startElement('events');
  339.  
  340. foreach ($event_ids as $event_id) {
  341. // Defensive skip if meta somehow says remove
  342. $remove_flag = get_post_meta($event_id, 'remove_from_export', true);
  343. if ($remove_flag === '1' || $remove_flag === 1) continue;
  344.  
  345. $event_uuid = wp_generate_uuid4();
  346.  
  347. // Post fields
  348. $title = get_the_title($event_id) ?: '';
  349. $content = apply_filters('the_content', (string) get_post_field('post_content', $event_id));
  350. $image = get_the_post_thumbnail_url($event_id, 'full');
  351. $ticket = (string) get_field('edgtf_tickets', $event_id);
  352.  
  353. // Categories (adjust as needed)
  354. $main_cat = 'Musik';
  355. $subcats = get_the_terms($event_id, 'offbeat-event-category');
  356. $subcat_name = ($subcats && !is_wp_error($subcats)) ? $subcats[0]->name : '';
  357.  
  358. // ACF date/time
  359. $start_date = get_field('edgtf_event_start_date', $event_id);
  360. $end_date = get_field('edgtf_event_end_date', $event_id);
  361. $start_time = get_field('edgtf_event_start_time', $event_id);
  362. $end_time = get_field('edgtf_event_end_time', $event_id);
  363.  
  364. // Interval
  365. [$start_dt, $end_dt] = minasa_build_interval_v2($start_date, $end_date, $start_time, $end_time);
  366.  
  367. // Location
  368. $loc_terms = get_the_terms($event_id, 'event_location');
  369. $loc_term = ($loc_terms && !is_wp_error($loc_terms)) ? $loc_terms[0] : null;
  370. $location_uuid = null;
  371. if ($loc_term) {
  372. $tid = (int) $loc_term->term_id;
  373. if (!isset($location_map[$tid])) {
  374. $location_map[$tid] = [
  375. 'uuid' => wp_generate_uuid4(),
  376. 'data' => collect_location_term_payload($loc_term, $data_provider_uuid),
  377. ];
  378. }
  379. $location_uuid = $location_map[$tid]['uuid'];
  380. $touched_locations[$location_uuid] = true;
  381. }
  382.  
  383. // Organizer
  384. $org_payload = resolve_organizer_for_post($event_id, $data_provider_uuid);
  385. $org_key = $org_payload['key'];
  386. if (!isset($organizer_map[$org_key])) {
  387. $organizer_map[$org_key] = [
  388. 'uuid' => $org_payload['uuid'],
  389. 'data' => $org_payload['data'],
  390. ];
  391. }
  392. $organizer_uuid = $organizer_map[$org_key]['uuid'];
  393. $touched_organizers[$organizer_uuid] = true;
  394.  
  395. // <event>
  396. $writer->startElement('event');
  397. $writer->writeElement('uuid7', $event_uuid);
  398. if ($location_uuid) $writer->writeElement('locationUuid7', $location_uuid);
  399. $writer->writeElement('organizerUuid7', $organizer_uuid);
  400. $writer->writeElement('dataProviderUuid7', $data_provider_uuid);
  401.  
  402. $writer->writeElement('created', get_the_date(DATE_ATOM, $event_id));
  403. $writer->writeElement('modified', get_post_modified_time(DATE_ATOM, false, $event_id));
  404. $writer->writeElement('published', get_the_date(DATE_ATOM, $event_id));
  405.  
  406. $writer->writeElement('eventClass', 'event');
  407. $writer->writeElement('eventMode', $location_uuid ? 'offline' : 'online');
  408.  
  409. $writer->startElement('category');
  410. $writer->writeElement('mainCategory', $main_cat);
  411. // if ($subcat_name) $writer->writeElement('secondaryCategory', $subcat_name);
  412. $writer->endElement();
  413.  
  414. if ($image) $writer->writeElement('imageUrl', esc_url_raw($image));
  415. $writer->writeElement('title', wp_strip_all_tags($title));
  416.  
  417. $writer->startElement('description');
  418. $writer->writeCData($content);
  419. $writer->endElement();
  420.  
  421. if (!empty($ticket)) $writer->writeElement('presaleUrl', esc_url_raw($ticket));
  422.  
  423. // duration (dates only)
  424. $writer->startElement('duration');
  425. $dur_from = null;
  426. $dur_to = null;
  427. if ($start_date) {
  428. $dur_from = preg_replace('/(\d{4})[-\/.]?(\d{2})[-\/.]?(\d{2})/', '$1-$2-$3', $start_date);
  429. $writer->writeElement('from', $dur_from);
  430. }
  431. if ($end_date ?: $start_date) {
  432. $to = $end_date ?: $start_date;
  433. $dur_to = preg_replace('/(\d{4})[-\/.]?(\d{2})[-\/.]?(\d{2})/', '$1-$2-$3', $to);
  434. $writer->writeElement('to', $dur_to);
  435. }
  436. $writer->endElement(); // duration
  437.  
  438. // schedules
  439. if ($start_dt) {
  440. // Align schedules' calendar dates with duration (keep time)
  441. if (!empty($dur_from)) {
  442. $from_dt = DateTime::createFromFormat('Y-m-d', $dur_from, $site_tz);
  443. if ($from_dt instanceof DateTime && $start_dt->format('Y-m-d') !== $from_dt->format('Y-m-d')) {
  444. $start_dt->setDate((int)$from_dt->format('Y'), (int)$from_dt->format('m'), (int)$from_dt->format('d'));
  445. }
  446. }
  447. if (!empty($dur_to) && $end_dt instanceof DateTime && empty($end_time)) {
  448. $to_dt = DateTime::createFromFormat('Y-m-d', $dur_to, $site_tz);
  449. if ($to_dt instanceof DateTime && $end_dt->format('Y-m-d') !== $to_dt->format('Y-m-d')) {
  450. $end_dt->setDate((int)$to_dt->format('Y'), (int)$to_dt->format('m'), (int)$to_dt->format('d'));
  451. }
  452. }
  453.  
  454. $writer->startElement('schedules');
  455. $writer->startElement('schedule');
  456. $writer->writeElement('uuid7', wp_generate_uuid4());
  457. if ($location_uuid) $writer->writeElement('locationUuid7', $location_uuid);
  458. $writer->writeElement('created', get_the_date(DATE_ATOM, $event_id));
  459. $writer->writeElement('modified', get_post_modified_time(DATE_ATOM, false, $event_id));
  460. $writer->writeElement('eventStatus', 'scheduled');
  461.  
  462. $writer->writeElement('start', (clone $start_dt)->setTimezone($site_tz)->format(DATE_ATOM));
  463. $writer->writeElement('end', (clone $end_dt)->setTimezone($site_tz)->format(DATE_ATOM));
  464.  
  465. $writer->startElement('recurrence');
  466. $writer->writeElement('frequency', 'single');
  467. $writer->endElement();
  468. $writer->writeElement('soldOut', 'false');
  469. $writer->endElement(); // schedule
  470. $writer->endElement(); // schedules
  471. } else {
  472. error_log("[Minasa] Skipped schedules for event #{$event_id} — no parsable start date/time");
  473. }
  474.  
  475. // providerReference
  476. $writer->startElement('providerReference');
  477. $writer->writeElement('id', (string)$event_id);
  478. $writer->writeElement('url', get_permalink($event_id));
  479. $writer->endElement();
  480.  
  481. $writer->endElement(); // </event>
  482. }
  483. $writer->endElement(); // </events>
  484.  
  485. /*----------------------------------
  486. | <locations> (only those referenced)
  487. ----------------------------------*/
  488. $writer->startElement('locations');
  489. foreach ($location_map as $term_id => $payload) {
  490. $uuid = $payload['uuid'];
  491. if (empty($touched_locations[$uuid])) continue;
  492. $d = $payload['data'];
  493.  
  494. $writer->startElement('location');
  495. $writer->writeElement('uuid7', $uuid);
  496. if (!empty($d['organizerUuid7'])) $writer->writeElement('organizerUuid7', $d['organizerUuid7']);
  497. if (!empty($d['dataProviderUuid7'])) $writer->writeElement('dataProviderUuid7', $d['dataProviderUuid7']);
  498. $writer->writeElement('created', $d['created']);
  499. $writer->writeElement('modified', $d['modified']);
  500.  
  501. if (!empty($d['providerReference'])) {
  502. $writer->startElement('providerReference');
  503. if (!empty($d['providerReference']['id'])) $writer->writeElement('id', $d['providerReference']['id']);
  504. if (!empty($d['providerReference']['url'])) $writer->writeElement('url', $d['providerReference']['url']);
  505. $writer->endElement();
  506. }
  507.  
  508. if (!empty($d['imageUrl'])) $writer->writeElement('imageUrl', $d['imageUrl']);
  509.  
  510. $writer->startElement('address');
  511. $writer->writeElement('legalType', 'organization');
  512. if (!empty($d['title'])) $writer->writeElement('title', $d['title']);
  513. if (!empty($d['street'])) $writer->writeElement('street', $d['street']);
  514. if (!empty($d['zip'])) $writer->writeElement('zip', $d['zip']);
  515. if (!empty($d['city'])) $writer->writeElement('city', $d['city']);
  516. $writer->writeElement('country', $d['country'] ?: 'CH');
  517. if (!empty($d['phone'])) $writer->writeElement('phone', $d['phone']);
  518. if (!empty($d['email'])) $writer->writeElement('email', $d['email']);
  519. if (!empty($d['url'])) $writer->writeElement('url', $d['url']);
  520. $writer->endElement(); // address
  521.  
  522. $writer->startElement('contacts'); $writer->endElement();
  523. $writer->endElement(); // location
  524. }
  525. $writer->endElement(); // </locations>
  526.  
  527. /*----------------------------------
  528. | <organizers> (only those referenced)
  529. ----------------------------------*/
  530. $writer->startElement('organizers');
  531. foreach ($organizer_map as $key => $payload) {
  532. $uuid = $payload['uuid'];
  533. if (empty($touched_organizers[$uuid])) continue;
  534. $d = $payload['data'];
  535.  
  536. $writer->startElement('organizer');
  537. $writer->writeElement('uuid7', $uuid);
  538. $writer->writeElement('dataProviderUuid7', $d['dataProviderUuid7']);
  539. $writer->writeElement('created', $d['created']);
  540. $writer->writeElement('modified', $d['modified']);
  541. if (!empty($d['imageUrl'])) $writer->writeElement('imageUrl', $d['imageUrl']);
  542.  
  543. if (!empty($d['providerReference'])) {
  544. $writer->startElement('providerReference');
  545. if (!empty($d['providerReference']['id'])) $writer->writeElement('id', $d['providerReference']['id']);
  546. if (!empty($d['providerReference']['url'])) $writer->writeElement('url', $d['providerReference']['url']);
  547. $writer->endElement();
  548. }
  549.  
  550. $writer->startElement('address');
  551. $writer->writeElement('legalType', 'organization');
  552. if (!empty($d['title'])) $writer->writeElement('title', $d['title']);
  553. if (!empty($d['zip'])) $writer->writeElement('zip', $d['zip']);
  554. if (!empty($d['city'])) $writer->writeElement('city', $d['city']);
  555. $writer->writeElement('country', $d['country'] ?: 'CH');
  556. if (!empty($d['email'])) $writer->writeElement('email', $d['email']);
  557. if (!empty($d['url'])) $writer->writeElement('url', $d['url']);
  558. $writer->endElement(); // address
  559.  
  560. $writer->startElement('contacts'); $writer->endElement();
  561. $writer->endElement(); // organizer
  562. }
  563. $writer->endElement(); // </organizers>
  564.  
  565. /*----------------------------------
  566. | <dataProviders>
  567. ----------------------------------*/
  568. $writer->startElement('dataProviders');
  569. $writer->startElement('dataProvider');
  570. $writer->writeElement('uuid7', $data_provider_uuid);
  571. $writer->writeElement('provider', $data_provider_name);
  572. $writer->endElement();
  573. $writer->endElement(); // </dataProviders>
  574.  
  575. $writer->endElement(); // </minasa>
  576. $writer->endDocument();
  577. $writer->flush();
  578. }
  579.  
  580.  
  581.  
  582. add_action('admin_init', function () {
  583. if (isset($_GET['regen_azizi_xml']) && current_user_can('manage_options')) {
  584. generate_azizi_xml(ABSPATH . 'azizi.xml');
  585. wp_die('Azizi XML regenerated at ' . ABSPATH . 'azizi.xml');
  586. }
  587. });
Advertisement
Add Comment
Please, Sign In to add comment