Files
KGV-Verein-Manager/includes/Repositories/AssignmentRepository.php
2026-04-13 21:01:07 +02:00

280 lines
8.0 KiB
PHP

<?php
/**
* Parcel/member and parcel/tenant assignments.
*
* @package KGV\VereinManager
*/
namespace KGV\VereinManager\Repositories;
use KGV\VereinManager\Roles;
use KGV\VereinManager\Schema;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class AssignmentRepository {
/**
* WordPress database object.
*
* @var \wpdb
*/
private $wpdb;
/**
* Member assignment table.
*
* @var string
*/
private $member_table;
/**
* Tenant assignment table.
*
* @var string
*/
private $tenant_table;
/**
* Construct repository.
*/
public function __construct() {
global $wpdb;
$this->wpdb = $wpdb;
$this->member_table = Schema::table( 'parcel_members' );
$this->tenant_table = Schema::table( 'parcel_tenants' );
}
/**
* Get WordPress users with the role "Mitglied".
*
* @return array
*/
public function get_member_users() {
$query = new \WP_User_Query(
array(
'role' => Roles::MEMBER_ROLE,
'orderby' => 'display_name',
'order' => 'ASC',
'number' => 500,
)
);
return $query->get_results();
}
/**
* Get assigned member IDs for a parcel.
*
* @param int $parcel_id Parcel ID.
* @return array
*/
public function get_member_ids_for_parcel( $parcel_id ) {
$ids = $this->wpdb->get_col( $this->wpdb->prepare( "SELECT user_id FROM {$this->member_table} WHERE parcel_id = %d", $parcel_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
return array_map( 'absint', $ids );
}
/**
* Get all members assigned to one parcel.
*
* @param int $parcel_id Parcel ID.
* @return array
*/
public function get_members_for_parcel( $parcel_id ) {
$users = $this->wpdb->users;
$sql = "SELECT u.ID, u.display_name, u.user_email
FROM {$this->member_table} pm
INNER JOIN {$users} u ON u.ID = pm.user_id
WHERE pm.parcel_id = %d
ORDER BY u.display_name ASC";
return $this->wpdb->get_results( $this->wpdb->prepare( $sql, $parcel_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Get all parcels assigned to a specific user.
*
* @param int $user_id User ID.
* @return array
*/
public function get_parcels_for_user( $user_id ) {
$parcels = Schema::table( 'parcels' );
$sections = Schema::table( 'sections' );
$meters = Schema::table( 'meters' );
$sql = "SELECT p.*, s.name AS section_name,
(SELECT meter_number FROM {$meters} wm WHERE wm.parcel_id = p.id AND wm.type = 'water' LIMIT 1) AS water_meter_number,
(SELECT meter_number FROM {$meters} em WHERE em.parcel_id = p.id AND em.type = 'power' LIMIT 1) AS power_meter_number
FROM {$this->member_table} pm
INNER JOIN {$parcels} p ON p.id = pm.parcel_id
LEFT JOIN {$sections} s ON s.id = p.section_id
WHERE pm.user_id = %d
ORDER BY s.name ASC, p.label ASC";
return $this->wpdb->get_results( $this->wpdb->prepare( $sql, $user_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Check whether a parcel belongs to a given user.
*
* @param int $user_id User ID.
* @param int $parcel_id Parcel ID.
* @return bool
*/
public function user_has_parcel( $user_id, $parcel_id ) {
$sql = "SELECT COUNT(*) FROM {$this->member_table} WHERE user_id = %d AND parcel_id = %d";
return (int) $this->wpdb->get_var( $this->wpdb->prepare( $sql, $user_id, $parcel_id ) ) > 0; // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Get assigned tenant IDs for a parcel.
*
* @param int $parcel_id Parcel ID.
* @return array
*/
public function get_tenant_ids_for_parcel( $parcel_id ) {
$ids = $this->wpdb->get_col( $this->wpdb->prepare( "SELECT tenant_id FROM {$this->tenant_table} WHERE parcel_id = %d", $parcel_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
return array_map( 'absint', $ids );
}
/**
* Get all members linked to a tenant via assigned parcels.
*
* @param int $tenant_id Tenant ID.
* @return array
*/
public function get_members_for_tenant( $tenant_id ) {
$parcels = Schema::table( 'parcels' );
$users = $this->wpdb->users;
$sql = "SELECT DISTINCT u.ID, u.display_name, u.user_email, p.label AS parcel_label
FROM {$this->tenant_table} pt
INNER JOIN {$parcels} p ON p.id = pt.parcel_id
INNER JOIN {$this->member_table} pm ON pm.parcel_id = pt.parcel_id
INNER JOIN {$users} u ON u.ID = pm.user_id
WHERE pt.tenant_id = %d
ORDER BY p.label ASC, u.display_name ASC";
return $this->wpdb->get_results( $this->wpdb->prepare( $sql, $tenant_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Get all tenants assigned to one parcel.
*
* @param int $parcel_id Parcel ID.
* @return array
*/
public function get_tenants_for_parcel( $parcel_id ) {
$tenants = Schema::table( 'tenants' );
$sql = "SELECT t.*
FROM {$this->tenant_table} pt
INNER JOIN {$tenants} t ON t.id = pt.tenant_id
WHERE pt.parcel_id = %d
ORDER BY t.last_name ASC, t.first_name ASC";
return $this->wpdb->get_results( $this->wpdb->prepare( $sql, $parcel_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Get all parcels assigned to one tenant.
*
* @param int $tenant_id Tenant ID.
* @return array
*/
public function get_parcels_for_tenant( $tenant_id ) {
$parcels = Schema::table( 'parcels' );
$sections = Schema::table( 'sections' );
$sql = "SELECT p.*, s.name AS section_name
FROM {$this->tenant_table} pt
INNER JOIN {$parcels} p ON p.id = pt.parcel_id
LEFT JOIN {$sections} s ON s.id = p.section_id
WHERE pt.tenant_id = %d
ORDER BY s.name ASC, p.label ASC";
return $this->wpdb->get_results( $this->wpdb->prepare( $sql, $tenant_id ) ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Synchronize member assignments.
*
* @param int $parcel_id Parcel ID.
* @param array $user_ids User IDs.
* @return void
*/
public function sync_member_ids( $parcel_id, $user_ids ) {
$user_ids = array_values( array_unique( array_filter( array_map( 'absint', (array) $user_ids ) ) ) );
$this->wpdb->delete( $this->member_table, array( 'parcel_id' => $parcel_id ), array( '%d' ) );
foreach ( $user_ids as $user_id ) {
$this->wpdb->insert(
$this->member_table,
array(
'parcel_id' => $parcel_id,
'user_id' => $user_id,
'created_at' => current_time( 'mysql' ),
),
array( '%d', '%d', '%s' )
);
}
}
/**
* Synchronize tenant assignments.
*
* @param int $parcel_id Parcel ID.
* @param array $tenant_ids Tenant IDs.
* @return void
*/
public function sync_tenant_ids( $parcel_id, $tenant_ids ) {
$tenant_ids = array_values( array_unique( array_filter( array_map( 'absint', (array) $tenant_ids ) ) ) );
$this->wpdb->delete( $this->tenant_table, array( 'parcel_id' => $parcel_id ), array( '%d' ) );
foreach ( $tenant_ids as $tenant_id ) {
$this->wpdb->insert(
$this->tenant_table,
array(
'parcel_id' => $parcel_id,
'tenant_id' => $tenant_id,
'created_at' => current_time( 'mysql' ),
),
array( '%d', '%d', '%s' )
);
}
}
/**
* Check whether a member is assigned to a different parcel.
*
* @param int $user_id User ID.
* @param int $parcel_id Current parcel ID.
* @return bool
*/
public function member_has_other_parcels( $user_id, $parcel_id ) {
$sql = "SELECT COUNT(*) FROM {$this->member_table} WHERE user_id = %d AND parcel_id != %d";
return (int) $this->wpdb->get_var( $this->wpdb->prepare( $sql, $user_id, $parcel_id ) ) > 0; // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
}
/**
* Remove all assignments for a parcel.
*
* @param int $parcel_id Parcel ID.
* @return void
*/
public function purge_parcel( $parcel_id ) {
$this->wpdb->delete( $this->member_table, array( 'parcel_id' => $parcel_id ), array( '%d' ) );
$this->wpdb->delete( $this->tenant_table, array( 'parcel_id' => $parcel_id ), array( '%d' ) );
}
/**
* Remove all tenant relations before deleting the tenant.
*
* @param int $tenant_id Tenant ID.
* @return void
*/
public function purge_tenant( $tenant_id ) {
$this->wpdb->delete( $this->tenant_table, array( 'tenant_id' => $tenant_id ), array( '%d' ) );
}
}