Files
2026-04-13 15:52:42 +02:00

746 lines
23 KiB
PHP
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Plugin Name: Elementor Addon
* Description: Simple hello world widgets for Elementor.
* Version: 1.0.0
* Author: Elementor Developer
* Author URI: https://developers.elementor.com/
* Text Domain: elementor-addon
*
* Requires Plugins: elementor
* Elementor tested up to: 3.21.0
* Elementor Pro tested up to: 3.21.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Formatuje kwotÄ™ do postaci 1 000 000,00.
*
* @param mixed $price Surowa wartość ceny.
* @return string
*/
function elementor_addon_format_price( $price ) {
if ( '' === $price || null === $price ) {
return '';
}
$value = wp_strip_all_tags( (string) $price );
$value = str_replace( [ "\xc2\xa0", ' ', 'zł', 'zl' ], '', $value );
$value = preg_replace( '/[^\d,.\-]/u', '', $value );
if ( '' === $value || null === $value ) {
return '';
}
$last_comma = strrpos( $value, ',' );
$last_dot = strrpos( $value, '.' );
if ( false !== $last_comma && false !== $last_dot ) {
if ( $last_comma > $last_dot ) {
$value = str_replace( '.', '', $value );
$value = str_replace( ',', '.', $value );
} else {
$value = str_replace( ',', '', $value );
}
} elseif ( false !== $last_comma ) {
$value = str_replace( '.', '', $value );
$value = str_replace( ',', '.', $value );
} else {
$parts = explode( '.', $value );
if ( count( $parts ) > 2 ) {
$decimal = array_pop( $parts );
$value = implode( '', $parts ) . '.' . $decimal;
}
}
if ( ! is_numeric( $value ) ) {
return trim( (string) $price );
}
return number_format_i18n( (float) $value, 0 );
}
/**
* Register widget files
*/
function register_hello_world_widget( $widgets_manager ) {
require_once( __DIR__ . '/widgets/apartaments.php' );
require_once( __DIR__ . '/widgets/parking-spots.php' );
$widgets_manager->register( new \Elementor_Apartaments() );
$widgets_manager->register( new \Elementor_Parking_Spots() );
}
add_action( 'elementor/widgets/register', 'register_hello_world_widget' );
/**
* Register scripts/styles only.
* Do not enqueue them globally.
*/
function elementor_addon_register_assets() {
// Swiper CSS
wp_register_style(
'elementor-addon-swiper',
plugins_url( 'plugins/swiper/swiper-bundle.min.css', __FILE__ ),
[],
'11.0.0'
);
// Fancybox CSS
wp_register_style(
'elementor-addon-fancybox',
'https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.css',
[],
'5.0'
);
// Widget CSS
wp_register_style(
'elementor-addon-main-css',
plugins_url( 'assets/css/main.css', __FILE__ ),
[ 'elementor-addon-swiper', 'elementor-addon-fancybox' ],
'1.0.0'
);
// Swiper JS
wp_register_script(
'elementor-addon-swiper',
plugins_url( 'plugins/swiper/swiper-bundle.min.js', __FILE__ ),
[],
'11.0.0',
true
);
// Fancybox JS
wp_register_script(
'elementor-addon-fancybox',
'https://cdn.jsdelivr.net/npm/@fancyapps/ui@5.0/dist/fancybox/fancybox.umd.js',
[],
'5.0',
true
);
// Widget JS
wp_register_script(
'elementor-addon-main-js',
plugins_url( 'assets/js/main.js', __FILE__ ),
[ 'jquery', 'elementor-addon-swiper', 'elementor-addon-fancybox' ],
'1.0.0',
true
);
}
add_action( 'wp_enqueue_scripts', 'elementor_addon_register_assets' );
/**
* PrzekaĹĽ dane do JS (ajaxUrl + nonce) gdy skrypt jest enqueue'owany przez widget.
*/
function elementor_addon_localize_scripts() {
wp_localize_script( 'elementor-addon-main-js', 'apartamentsData', [
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'apartamenty_price_history_nonce' ),
] );
}
add_action( 'wp_enqueue_scripts', 'elementor_addon_localize_scripts', 20 );
/**
* Włącza wsparcie "Atrybuty wpisu" (menu_order) dla CPT apartamenty,
* aby można było ręcznie ustawiać kolejność.
*/
function elementor_addon_enable_apartamenty_menu_order( $args, $post_type ) {
if ( 'apartamenty' !== $post_type ) {
return $args;
}
$supports = $args['supports'] ?? [];
if ( true === $supports || false === $supports ) {
$supports = [ 'title', 'editor' ];
}
if ( ! is_array( $supports ) ) {
$supports = (array) $supports;
}
if ( ! in_array( 'page-attributes', $supports, true ) ) {
$supports[] = 'page-attributes';
}
$args['supports'] = $supports;
return $args;
}
add_filter( 'register_post_type_args', 'elementor_addon_enable_apartamenty_menu_order', 20, 2 );
// ===========================================================
// HISTORIA CEN — TABELA DB
// ===========================================================
/**
* Tworzy tabelę wp_price_history jeśli nie istnieje lub wersja DB jest stara.
*/
function elementor_addon_create_price_history_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'price_history';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE {$table_name} (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
post_id BIGINT UNSIGNED NOT NULL,
price VARCHAR(50) NOT NULL DEFAULT '',
price_m2 VARCHAR(50) NOT NULL DEFAULT '',
floor_space VARCHAR(50) NOT NULL DEFAULT '',
recorded_at DATE NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY unique_daily (post_id, recorded_at),
KEY idx_post_id (post_id)
) ENGINE=InnoDB {$charset_collate};";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta( $sql );
}
/**
* Tworzy tabelÄ™ wp_parking_price_history dla miejsc postojowych.
*/
function elementor_addon_create_parking_price_history_table() {
global $wpdb;
$table_name = $wpdb->prefix . 'parking_price_history';
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE {$table_name} (
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
parking_type VARCHAR(50) NOT NULL,
price VARCHAR(50) NOT NULL DEFAULT '',
price_m2 VARCHAR(50) NOT NULL DEFAULT '',
recorded_at DATE NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY unique_daily (parking_type, recorded_at),
KEY idx_type (parking_type)
) ENGINE=InnoDB {$charset_collate};";
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
dbDelta( $sql );
}
/**
* Tworzy obie tabele przy aktywacji pluginu.
*/
function elementor_addon_create_tables() {
elementor_addon_create_price_history_table();
elementor_addon_create_parking_price_history_table();
update_option( 'elementor_addon_db_version', '1.1' );
}
register_activation_hook( __FILE__, 'elementor_addon_create_tables' );
/**
* Sprawdza wersję DB przy każdym init i tworzy tabele jeśli brakuje.
*/
function elementor_addon_maybe_update_db() {
if ( get_option( 'elementor_addon_db_version' ) !== '1.1' ) {
elementor_addon_create_tables();
}
}
add_action( 'init', 'elementor_addon_maybe_update_db' );
// ===========================================================
// HISTORIA CEN — CRON DZIENNY
// ===========================================================
/**
* Rejestruje WP Cron jeśli jeszcze nie zaplanowany.
*/
function elementor_addon_schedule_cron() {
if ( ! wp_next_scheduled( 'apartamenty_record_prices' ) ) {
wp_schedule_event( time(), 'daily', 'apartamenty_record_prices' );
}
}
add_action( 'wp', 'elementor_addon_schedule_cron' );
/**
* Zapisuje aktualne ceny wszystkich apartamentÄĹw do tabeli historii.
* Używa INSERT IGNORE — jeden rekord na apartament na dzień.
*/
function elementor_addon_record_prices() {
global $wpdb;
delete_transient( 'apartamenty_price_xml_cache' );
$table_name = $wpdb->prefix . 'price_history';
$today = current_time( 'Y-m-d' );
$apartaments = new WP_Query( [
'post_type' => 'apartamenty',
'post_status' => 'publish',
'posts_per_page' => -1,
'fields' => 'ids',
] );
if ( empty( $apartaments->posts ) ) {
return;
}
foreach ( $apartaments->posts as $post_id ) {
$price = get_post_meta( $post_id, 'information_price', true );
$price_m2 = get_post_meta( $post_id, 'information_price_m2', true );
$floor_space = get_post_meta( $post_id, 'information_floor_space', true );
$wpdb->query(
$wpdb->prepare(
"INSERT IGNORE INTO {$table_name} (post_id, price, price_m2, floor_space, recorded_at)
VALUES (%d, %s, %s, %s, %s)",
$post_id,
(string) $price,
(string) $price_m2,
(string) $floor_space,
$today
)
);
}
// Miejsca postojowe - zapis cen z ACF options (pola w grupach)
$parking_table = $wpdb->prefix . 'parking_price_history';
$parking_groups = [
'zwykle' => 'miejsce_postojowe_zwykle',
'rodzinne' => 'miejsce_postojowe_rodzinne',
];
foreach ( $parking_groups as $type => $group_name ) {
$group = get_field( $group_name, 'option' ) ?: [];
$price = $group[ $group_name . '_cena' ] ?? '';
$price_m2 = $group[ $group_name . '_cena_m2' ] ?? '';
if ( $price || $price_m2 ) {
$wpdb->query(
$wpdb->prepare(
"INSERT IGNORE INTO {$parking_table} (parking_type, price, price_m2, recorded_at)
VALUES (%s, %s, %s, %s)",
$type,
(string) $price,
(string) $price_m2,
$today
)
);
}
}
}
add_action( 'apartamenty_record_prices', 'elementor_addon_record_prices' );
// ===========================================================
// HISTORIA CEN - AJAX ENDPOINT
// ===========================================================
/**
* Zwraca historię cen dla apartamentu jako JSON.
* Wymaga nonce: apartamenty_price_history_nonce
*/
function elementor_addon_get_price_history_ajax() {
global $wpdb;
if ( ! check_ajax_referer( 'apartamenty_price_history_nonce', 'nonce', false ) ) {
wp_send_json_error( [ 'message' => 'Invalid nonce' ] );
die();
}
$post_id = absint( $_POST['post_id'] ?? 0 );
if ( ! $post_id ) {
wp_send_json_error( [ 'message' => 'Invalid post_id' ] );
die();
}
$table_name = $wpdb->prefix . 'price_history';
$history = $wpdb->get_results(
$wpdb->prepare(
"SELECT recorded_at, price, price_m2, floor_space
FROM {$table_name}
WHERE post_id = %d
ORDER BY recorded_at DESC
LIMIT 50",
$post_id
)
);
wp_send_json_success( [
'title' => get_the_title( $post_id ),
'price' => get_post_meta( $post_id, 'information_price', true ),
'price_m2' => get_post_meta( $post_id, 'information_price_m2', true ),
'floor_space' => get_post_meta( $post_id, 'information_floor_space', true ),
'history' => $history,
] );
}
add_action( 'wp_ajax_apartamenty_get_price_history', 'elementor_addon_get_price_history_ajax' );
add_action( 'wp_ajax_nopriv_apartamenty_get_price_history', 'elementor_addon_get_price_history_ajax' );
/**
* Zwraca historię cen dla miejsca postojowego jako JSON.
* Parametr: parking_type ('zwykle' lub 'rodzinne')
*/
function elementor_addon_get_parking_price_history_ajax() {
global $wpdb;
if ( ! check_ajax_referer( 'apartamenty_price_history_nonce', 'nonce', false ) ) {
wp_send_json_error( [ 'message' => 'Invalid nonce' ] );
die();
}
$parking_type = sanitize_text_field( $_POST['parking_type'] ?? '' );
if ( ! in_array( $parking_type, [ 'zwykle', 'rodzinne' ], true ) ) {
wp_send_json_error( [ 'message' => 'Invalid parking_type' ] );
die();
}
$labels = [
'zwykle' => 'Miejsce postojowe pojedyncze',
'rodzinne' => 'Miejsce postojowe rodzinne',
];
$group_names = [
'zwykle' => 'miejsce_postojowe_zwykle',
'rodzinne' => 'miejsce_postojowe_rodzinne',
];
$table_name = $wpdb->prefix . 'parking_price_history';
$history = $wpdb->get_results(
$wpdb->prepare(
"SELECT recorded_at, price, price_m2
FROM {$table_name}
WHERE parking_type = %s
ORDER BY recorded_at DESC
LIMIT 50",
$parking_type
)
);
$group_name = $group_names[ $parking_type ];
$group = get_field( $group_name, 'option' ) ?: [];
wp_send_json_success( [
'title' => $labels[ $parking_type ],
'price' => $group[ $group_name . '_cena' ] ?? '',
'price_m2' => $group[ $group_name . '_cena_m2' ] ?? '',
'history' => $history,
] );
}
add_action( 'wp_ajax_parking_get_price_history', 'elementor_addon_get_parking_price_history_ajax' );
add_action( 'wp_ajax_nopriv_parking_get_price_history', 'elementor_addon_get_parking_price_history_ajax' );
// ===========================================================
// JAWNOŚĆ CEN — XML ENDPOINTS
// ===========================================================
/**
* Rejestruje reguĹ‚y przepisywania dla endpointÄĹw XML.
*/
function apartamenty_xml_rewrite_rules() {
add_rewrite_rule( '^ceny-mieszkan\.(xml|md5)$', 'index.php?apartamenty_xml=$matches[1]', 'top' );
add_rewrite_rule( '^dane-gov-pl\.(xml|md5)$', 'index.php?apartamenty_datagov=$matches[1]', 'top' );
}
add_action( 'init', 'apartamenty_xml_rewrite_rules', 10 );
/**
* Dodaje query vars dla endpointÄĹw XML.
*/
function apartamenty_xml_query_vars( $vars ) {
$vars[] = 'apartamenty_xml';
$vars[] = 'apartamenty_datagov';
return $vars;
}
add_filter( 'query_vars', 'apartamenty_xml_query_vars' );
/**
* Generuje XML z cenami wszystkich apartamentÄĹw.
* Wynik cachowany w transiencie na 1 godzinÄ™.
*
* @return string XML jako string
*/
function apartamenty_generate_price_xml() {
$cached = get_transient( 'apartamenty_price_xml_cache' );
if ( false !== $cached ) {
return $cached;
}
global $wpdb;
$table_name = $wpdb->prefix . 'price_history';
$query = new WP_Query( [
'post_type' => 'apartamenty',
'post_status' => 'publish',
'posts_per_page' => -1,
'orderby' => [
'menu_order' => 'ASC',
'title' => 'ASC',
],
] );
$x = function( $val ) {
return htmlspecialchars( (string) $val, ENT_XML1, 'UTF-8' );
};
$xml = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
$xml .= '<lokale inwestycja="Wyszy&#x144;skiego 12" generowany="' . $x( date( 'c' ) ) . '">' . "\n";
if ( $query->have_posts() ) {
foreach ( $query->posts as $post ) {
$post_id = $post->ID;
$type = get_post_meta( $post_id, 'information_type', true );
$floor = get_post_meta( $post_id, 'information_floor', true );
$floor_space = get_post_meta( $post_id, 'information_floor_space', true );
$price = get_post_meta( $post_id, 'information_price', true );
$price_m2 = get_post_meta( $post_id, 'information_price_m2', true );
$status = get_post_meta( $post_id, 'information_status', true );
$history = $wpdb->get_results(
$wpdb->prepare(
"SELECT recorded_at, price, price_m2
FROM {$table_name}
WHERE post_id = %d
ORDER BY recorded_at DESC",
$post_id
)
);
$last_update = ! empty( $history ) ? $history[0]->recorded_at : date( 'Y-m-d' );
$xml .= "\t" . '<lokal id="' . absint( $post_id ) . '">' . "\n";
$xml .= "\t\t<nazwa>" . $x( $post->post_title ) . "</nazwa>\n";
$xml .= "\t\t<typ>" . $x( $type ) . "</typ>\n";
$xml .= "\t\t<pietro>" . $x( $floor ) . "</pietro>\n";
$xml .= "\t\t<powierzchnia>" . $x( $floor_space ) . "</powierzchnia>\n";
$xml .= "\t\t<status>" . $x( $status ) . "</status>\n";
$xml .= "\t\t<cena_brutto>" . $x( $price ) . "</cena_brutto>\n";
$xml .= "\t\t<cena_za_m2>" . $x( $price_m2 ) . "</cena_za_m2>\n";
$xml .= "\t\t<data_aktualizacji>" . $x( $last_update ) . "</data_aktualizacji>\n";
$xml .= "\t\t<historia_cen>\n";
foreach ( $history as $row ) {
$xml .= "\t\t\t" . '<zmiana data="' . $x( $row->recorded_at ) . '">' . "\n";
$xml .= "\t\t\t\t<cena_brutto>" . $x( $row->price ) . "</cena_brutto>\n";
$xml .= "\t\t\t\t<cena_za_m2>" . $x( $row->price_m2 ) . "</cena_za_m2>\n";
$xml .= "\t\t\t</zmiana>\n";
}
$xml .= "\t\t</historia_cen>\n";
$xml .= "\t</lokal>\n";
}
}
// Miejsca postojowe
$parking_table = $wpdb->prefix . 'parking_price_history';
$parking_configs = [
'zwykle' => [
'label' => 'Miejsce postojowe zwykłe',
'group_name' => 'miejsce_postojowe_zwykle',
],
'rodzinne' => [
'label' => 'Miejsce postojowe rodzinne',
'group_name' => 'miejsce_postojowe_rodzinne',
],
];
$xml .= "\t<miejsca_postojowe>\n";
foreach ( $parking_configs as $type => $cfg ) {
$group = get_field( $cfg['group_name'], 'option' ) ?: [];
$price = $group[ $cfg['group_name'] . '_cena' ] ?? '';
$price_m2 = $group[ $cfg['group_name'] . '_cena_m2' ] ?? '';
$p_history = $wpdb->get_results(
$wpdb->prepare(
"SELECT recorded_at, price, price_m2
FROM {$parking_table}
WHERE parking_type = %s
ORDER BY recorded_at DESC",
$type
)
);
$last_update = ! empty( $p_history ) ? $p_history[0]->recorded_at : date( 'Y-m-d' );
$xml .= "\t\t" . '<miejsce_postojowe typ="' . $x( $type ) . '">' . "\n";
$xml .= "\t\t\t<nazwa>" . $x( $cfg['label'] ) . "</nazwa>\n";
$xml .= "\t\t\t<cena_brutto>" . $x( $price ) . "</cena_brutto>\n";
$xml .= "\t\t\t<cena_za_m2>" . $x( $price_m2 ) . "</cena_za_m2>\n";
$xml .= "\t\t\t<data_aktualizacji>" . $x( $last_update ) . "</data_aktualizacji>\n";
$xml .= "\t\t\t<historia_cen>\n";
foreach ( $p_history as $row ) {
$xml .= "\t\t\t\t" . '<zmiana data="' . $x( $row->recorded_at ) . '">' . "\n";
$xml .= "\t\t\t\t\t<cena_brutto>" . $x( $row->price ) . "</cena_brutto>\n";
$xml .= "\t\t\t\t\t<cena_za_m2>" . $x( $row->price_m2 ) . "</cena_za_m2>\n";
$xml .= "\t\t\t\t</zmiana>\n";
}
$xml .= "\t\t\t</historia_cen>\n";
$xml .= "\t\t</miejsce_postojowe>\n";
}
$xml .= "\t</miejsca_postojowe>\n";
$xml .= '</lokale>';
set_transient( 'apartamenty_price_xml_cache', $xml, HOUR_IN_SECONDS );
return $xml;
}
/**
* Generuje XML katalogu dane.gov.pl zgodny z XSD portalu.
*
* @return string XML jako string
*/
function apartamenty_generate_datagov_xml() {
$resource_url = home_url( '/ceny-mieszkan.xml' );
$last_update = date( 'Y-m-d\T00:00:00.000\Z' );
$x = function( $val ) {
return htmlspecialchars( (string) $val, ENT_XML1, 'UTF-8' );
};
$xml = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
$xml .= '<datasets xmlns:xsi="urn:otwarte-dane:harvester:1.0-rc1">' . "\n";
$xml .= "\t<dataset status=\"published\">\n";
$xml .= "\t\t<extIdent>wyszynskiego12-ceny-mieszkan-v1</extIdent>\n";
$xml .= "\t\t<title>\n";
$xml .= "\t\t\t<polish>Ceny mieszka&#x144; &#x2013; Wyszy&#x144;skiego 12</polish>\n";
$xml .= "\t\t</title>\n";
$xml .= "\t\t<description>\n";
$xml .= "\t\t\t<polish>Historia cen lokali mieszkalnych w inwestycji przy ul. Wyszy&#x144;skiego 12. Dane aktualizowane codziennie zgodnie z ustaw&#x105; o jawno&#x15B;ci cen.</polish>\n";
$xml .= "\t\t</description>\n";
$xml .= "\t\t<updateFrequency>daily</updateFrequency>\n";
$xml .= "\t\t<categories>REGI</categories>\n";
$xml .= "\t\t<resources>\n";
$xml .= "\t\t\t<resource status=\"published\">\n";
$xml .= "\t\t\t\t<extIdent>wyszynskiego12-ceny-xml-v1</extIdent>\n";
$xml .= "\t\t\t\t<url>" . $x( $resource_url ) . "</url>\n";
$xml .= "\t\t\t\t<title>\n";
$xml .= "\t\t\t\t\t<polish>Cennik lokali XML</polish>\n";
$xml .= "\t\t\t\t</title>\n";
$xml .= "\t\t\t\t<description>\n";
$xml .= "\t\t\t\t\t<polish>Plik XML z aktualnym cennikiem i histori&#x105; zmian cen wszystkich lokali</polish>\n";
$xml .= "\t\t\t\t</description>\n";
$xml .= "\t\t\t\t<availability>remote</availability>\n";
$xml .= "\t\t\t\t<lastUpdateDate>" . $x( $last_update ) . "</lastUpdateDate>\n";
$xml .= "\t\t\t</resource>\n";
$xml .= "\t\t</resources>\n";
$xml .= "\t\t<tags lang=\"pl\">\n";
$xml .= "\t\t\t<tag>mieszkania</tag>\n";
$xml .= "\t\t\t<tag>ceny</tag>\n";
$xml .= "\t\t\t<tag>deweloper</tag>\n";
$xml .= "\t\t\t<tag>jawno&#x15B;&#x107; cen</tag>\n";
$xml .= "\t\t\t<tag>historia cen</tag>\n";
$xml .= "\t\t</tags>\n";
$xml .= "\t</dataset>\n";
$xml .= '</datasets>';
return $xml;
}
/**
* ObsĹ‚uguje ĹĽÄ…dania do endpointÄĹw XML — wysyĹ‚a odpowiedĹş i koĹ„czy.
*/
function apartamenty_xml_template_redirect() {
$xml_type = get_query_var( 'apartamenty_xml' );
$datagov_type = get_query_var( 'apartamenty_datagov' );
if ( $xml_type ) {
$content = apartamenty_generate_price_xml();
if ( 'xml' === $xml_type ) {
header( 'Content-Type: application/xml; charset=UTF-8' );
echo $content;
} else {
header( 'Content-Type: text/plain; charset=UTF-8' );
echo md5( $content );
}
exit;
}
if ( $datagov_type ) {
$content = apartamenty_generate_datagov_xml();
if ( 'xml' === $datagov_type ) {
header( 'Content-Type: application/xml; charset=UTF-8' );
echo $content;
} else {
header( 'Content-Type: text/plain; charset=UTF-8' );
echo md5( $content );
}
exit;
}
}
add_action( 'template_redirect', 'apartamenty_xml_template_redirect', 1 );
// ===========================================================
// JAWNOŚĆ CEN — STRONA ADMINISTRACYJNA
// ===========================================================
/**
* Rejestruje stronę Jawność Cen w menu Narzędzia wp-admin.
*/
function apartamenty_jawnosc_cen_menu() {
add_management_page(
'Jawność Cen',
'Jawność Cen',
'manage_options',
'jawnosc-cen',
'apartamenty_jawnosc_cen_page'
);
}
add_action( 'admin_menu', 'apartamenty_jawnosc_cen_menu' );
/**
* Renderuje stronę administracyjną z URL-ami do zgłoszenia.
*/
function apartamenty_jawnosc_cen_page() {
$url_ceny = esc_url( home_url( '/ceny-mieszkan.xml' ) );
$url_datagov = esc_url( home_url( '/dane-gov-pl.xml' ) );
?>
<div class="wrap">
<h1>Jawność Cen — Wyszyńskiego 12</h1>
<div class="notice notice-info">
<p>Dane aktualizowane codziennie przez WP Cron. Zgłoś URL katalogu dane.gov.pl do administratora portalu: <strong>kontakt@dane.gov.pl</strong></p>
</div>
<table class="widefat" style="max-width:800px; margin-top:20px;">
<thead>
<tr>
<th>Plik</th>
<th>URL</th>
<th>Akcje</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Plik cen (dane)</strong></td>
<td><code><?php echo $url_ceny; ?></code></td>
<td>
<button class="button" onclick="copyUrl('<?php echo esc_js( $url_ceny ); ?>')">Kopiuj URL</button>
<a href="<?php echo $url_ceny; ?>" target="_blank" class="button">OtwÄĹrz XML</a>
</td>
</tr>
<tr>
<td><strong>Katalog dane.gov.pl</strong><br><em>(zgłoś Ministerstwu)</em></td>
<td><code><?php echo $url_datagov; ?></code></td>
<td>
<button class="button button-primary" onclick="copyUrl('<?php echo esc_js( $url_datagov ); ?>')">Kopiuj URL</button>
<a href="<?php echo $url_datagov; ?>" target="_blank" class="button">OtwÄĹrz XML</a>
</td>
</tr>
</tbody>
</table>
</div>
<script>
function copyUrl(url) {
navigator.clipboard.writeText(url).then(function() {
alert('Skopiowano: ' + url);
}).catch(function() {
prompt('Skopiuj URL:', url);
});
}
</script>
<?php
}