123 lines
4.3 KiB
PHP
123 lines
4.3 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Name: Association Profile
|
|
* Description: Structured diagnostic identity fields for HOA association channels.
|
|
* Version: 0.3.0
|
|
* MinVersion: 11.0
|
|
* MaxVersion: 12.0
|
|
*/
|
|
|
|
function assoc_profile_module() {}
|
|
|
|
require_once 'addon/assoc_profile/assoc_profile_data.php';
|
|
require_once 'addon/assoc_profile/assoc_profile_post.php';
|
|
require_once 'addon/assoc_profile/assoc_profile_view.php';
|
|
require_once 'addon/assoc_profile/assoc_profile_manage.php';
|
|
|
|
function assoc_profile_load() {
|
|
register_hook('load_pdl', 'addon/assoc_profile/assoc_profile.php', 'assoc_profile_load_pdl');
|
|
register_hook('profile_advanced','addon/assoc_profile/assoc_profile.php', 'assoc_profile_view_hook');
|
|
register_hook('profile_edit', 'addon/assoc_profile/assoc_profile.php', 'assoc_profile_edit_hook');
|
|
}
|
|
|
|
function assoc_profile_unload() {
|
|
unregister_hook('load_pdl', 'addon/assoc_profile/assoc_profile.php', 'assoc_profile_load_pdl');
|
|
unregister_hook('profile_advanced','addon/assoc_profile/assoc_profile.php', 'assoc_profile_view_hook');
|
|
unregister_hook('profile_edit', 'addon/assoc_profile/assoc_profile.php', 'assoc_profile_edit_hook');
|
|
}
|
|
|
|
function assoc_profile_load_pdl(&$b) {
|
|
// Load PDL layout only when this module is active.
|
|
if (!is_array($b) || empty($b['module']) || $b['module'] !== 'assoc_profile') {
|
|
return;
|
|
}
|
|
$layout = @file_get_contents('addon/assoc_profile/mod_assoc_profile.pdl');
|
|
if ($layout !== false) {
|
|
$b['layout'] = $layout;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// HELPERS — used by all files in this addon
|
|
// ----------------------------------------------------------------------------
|
|
|
|
function assoc_h($v) {
|
|
// HTML-escape a value for safe output.
|
|
return htmlspecialchars((string)$v, ENT_QUOTES, 'UTF-8');
|
|
}
|
|
|
|
function assoc_slug_from_address($addr) {
|
|
// Extract the local part of a channel@node address.
|
|
return explode('@', $addr)[0] ?? '';
|
|
}
|
|
|
|
function assoc_is_operator() {
|
|
// True only when the logged-in channel is the current page channel.
|
|
if (!local_channel()) return false;
|
|
$channel = App::get_channel();
|
|
return local_channel() === intval($channel['channel_id']);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// CSRF — used by manage and post handlers
|
|
// ----------------------------------------------------------------------------
|
|
|
|
function assoc_csrf_token() {
|
|
// Generate or return the session CSRF token as a hidden input.
|
|
if (empty($_SESSION['assoc_profile_csrf'])) {
|
|
$_SESSION['assoc_profile_csrf'] = bin2hex(random_bytes(16));
|
|
}
|
|
return '<input type="hidden" name="assoc_profile_csrf" value="' . assoc_h($_SESSION['assoc_profile_csrf']) . '">';
|
|
}
|
|
|
|
function assoc_verify_csrf() {
|
|
// Return true if the POST CSRF token matches the session token.
|
|
return isset($_POST['assoc_profile_csrf'], $_SESSION['assoc_profile_csrf'])
|
|
&& hash_equals($_SESSION['assoc_profile_csrf'], $_POST['assoc_profile_csrf']);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// CONTENT ROUTER
|
|
// ----------------------------------------------------------------------------
|
|
|
|
function assoc_profile_content() {
|
|
// Load assets and route /assoc_profile/manage/* requests.
|
|
if (function_exists('head_add_css')) {
|
|
head_add_css('/addon/assoc_profile/view/css/assoc_profile.css');
|
|
}
|
|
if (function_exists('head_add_js')) {
|
|
head_add_js('/addon/assoc_profile/view/js/assoc_profile.js');
|
|
}
|
|
|
|
$action = argv(1) ?? '';
|
|
|
|
if ($action !== 'manage') {
|
|
return '';
|
|
}
|
|
|
|
if (!assoc_is_operator()) {
|
|
return '<div class="civicinfra-notice civicinfra-warning">Operator access required.</div>';
|
|
}
|
|
|
|
$sub = argv(2) ?? '';
|
|
$slug = argv(3) ?? '';
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
return assoc_handle_post();
|
|
}
|
|
|
|
if (!$sub) return assoc_render_manage_index();
|
|
|
|
if ($sub === 'assoc') {
|
|
if (!$slug) return assoc_render_add_association_form();
|
|
return assoc_render_edit_association_form($slug);
|
|
}
|
|
|
|
if ($sub === 'fields') return assoc_render_fields_form();
|
|
|
|
if ($sub === 'import') return assoc_render_import_form();
|
|
|
|
return '<div class="civicinfra-notice civicinfra-warning">Unknown management action.</div>';
|
|
}
|