PluginProbe
Easy Hotel – Powerful Hotel Booking / trunk
Easy Hotel – Powerful Hotel Booking vtrunk
2.0.8 2.0.7 2.0.6 2.0.5 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 1.9.9 1.9.8 1.9.7 1.9.6 1.9.5 1.9.4 1.9.3 1.9.2 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 All 110 releases
easy-hotel / pms / pms.php

pms.php in Easy Hotel – Powerful Hotel Booking trunk, at pms/pms.php

213 lines 7.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Easy Hotel - PMS module bootstrap.
4 *
5 * This module is fully self contained. It NEVER writes to the meta keys owned by the
6 * booking engine (`eshb_accomodation_metaboxes`, `eshb_booking_metaboxes`), it only reads
7 * from them, and it never takes part in the availability calculation. Removing the
8 * `include` of this file from easy-hotel.php restores the plugin to its previous behaviour
9 * with zero side effects.
10 *
11 * Architecture (mirrors the room-type / sub-unit split used by mature hotel PMS software):
12 *
13 * Layer 1 - required : accommodation (room type) + `total_rooms` -> owned by the booking engine
14 * Layer 2 - optional : unit labels + per booking unit assignment -> owned by this module
15 *
16 * Layer 2 is decorative for the booking engine: a booking with no unit assigned is a
17 * perfectly valid booking, exactly like it was before this module existed.
18 *
19 * @package Easy_Hotel\PMS
20 * @since 1.0.0
21 */
22
23 if ( ! defined( 'ABSPATH' ) ) {
24 exit; // Exit if accessed directly.
25 }
26
27 if ( defined( 'ESHB_PMS_VERSION' ) ) {
28 return; // Already loaded.
29 }
30
31 define( 'ESHB_PMS_VERSION', '1.0.0' );
32 define( 'ESHB_PMS_PATH', plugin_dir_path( __FILE__ ) );
33 define( 'ESHB_PMS_URL', plugin_dir_url( __FILE__ ) );
34
35 /**
36 * Post meta key holding the accommodation unit list.
37 *
38 * The unit editor lives in a "Rooms" tab inside the engine's own accommodation metabox, so the
39 * framework would otherwise store the rows in the engine's serialized array. It does not:
40 * `ESHB_PMS_Accommodation_Metabox::extract_units()` moves them into this key on every save, so
41 * engine meta stays untouched and the rows survive the module being removed.
42 * Shape: array{units: array<int, array{label:string, floor:string}>}
43 */
44 define( 'ESHB_PMS_UNITS_META', 'eshb_pms_units_metaboxes' );
45
46 /**
47 * Metabox unique key for the per booking unit assignment.
48 * Shape: array{units: int[], auto_assign: string} — one slot per booked room inside `units`,
49 * where `0` means "not assigned" (the nullable state).
50 */
51 define( 'ESHB_PMS_ASSIGN_META', 'eshb_pms_assignment_metaboxes' );
52
53 /**
54 * Key holding the unit rows / assignment slots inside both meta arrays. It is also the
55 * assignment metabox's field ID; the accommodation side uses the prefixed
56 * `ESHB_PMS_Accommodation_Metabox::FIELD_ID` on the form, because that field is rendered
57 * inside a metabox owned by the engine.
58 */
59 define( 'ESHB_PMS_UNITS_FIELD', 'units' );
60
61 /** Option key holding the module settings. */
62 define( 'ESHB_PMS_OPTION', 'eshb_pms_options' );
63
64 require_once ESHB_PMS_PATH . 'includes/class.pms-units.php';
65 require_once ESHB_PMS_PATH . 'includes/class.pms-assignment.php';
66 require_once ESHB_PMS_PATH . 'includes/class.pms-accommodation-metabox.php';
67 require_once ESHB_PMS_PATH . 'includes/class.pms-booking-metabox.php';
68 require_once ESHB_PMS_PATH . 'includes/class.pms-rack.php';
69 require_once ESHB_PMS_PATH . 'includes/class.pms-ajax.php';
70
71 /**
72 * Module bootstrapper.
73 */
74 final class ESHB_PMS {
75
76 /**
77 * Singleton instance.
78 *
79 * @var ESHB_PMS|null
80 */
81 private static $instance = null;
82
83 /**
84 * Returns the shared instance.
85 *
86 * @return ESHB_PMS
87 */
88 public static function instance() {
89
90 if ( is_null( self::$instance ) ) {
91 self::$instance = new self();
92 }
93
94 return self::$instance;
95 }
96
97 /**
98 * Registers every hook owned by the module.
99 */
100 private function __construct() {
101
102 /*
103 * The metaboxes are declared through the plugin's own settings framework, which
104 * collects them on `plugins_loaded` and instantiates them on `init`. Priority 20
105 * keeps our declarations after the booking engine's own ones, so on `save_post` the
106 * engine has already written `eshb_booking_metaboxes` when we validate against it.
107 */
108 add_action( 'plugins_loaded', [ ESHB_PMS_Accommodation_Metabox::class, 'register' ], 20 );
109 add_action( 'plugins_loaded', [ ESHB_PMS_Booking_Metabox::class, 'register' ], 20 );
110
111 // Room rack (tape chart) admin page.
112 ESHB_PMS_Rack::register();
113
114 // Ajax endpoints.
115 ESHB_PMS_Ajax::register();
116
117 // Optional auto assignment when a booking is created outside the admin screens.
118 add_action( 'added_post_meta', [ $this, 'maybe_auto_assign' ], 20, 4 );
119 add_action( 'updated_post_meta', [ $this, 'maybe_auto_assign' ], 20, 4 );
120
121 // Housekeeping of our own meta.
122 add_action( 'before_delete_post', [ $this, 'cleanup_booking_meta' ] );
123 }
124
125 /**
126 * Reads a module setting.
127 *
128 * @param string $key Setting key.
129 * @param mixed $default Fallback value.
130 *
131 * @return mixed
132 */
133 public static function get_option( $key, $default = '' ) {
134
135 $options = get_option( ESHB_PMS_OPTION, [] );
136
137 if ( ! is_array( $options ) || ! array_key_exists( $key, $options ) ) {
138 return $default;
139 }
140
141 return $options[ $key ];
142 }
143
144 /**
145 * Persists a set of module settings.
146 *
147 * @param array $values Key/value pairs to merge into the stored options.
148 */
149 public static function update_options( array $values ) {
150
151 $options = get_option( ESHB_PMS_OPTION, [] );
152 $options = is_array( $options ) ? $options : [];
153
154 update_option( ESHB_PMS_OPTION, array_merge( $options, $values ) );
155 }
156
157 /**
158 * Capability required to operate the PMS screens.
159 *
160 * @return string
161 */
162 public static function capability() {
163 return apply_filters( 'eshb_pms_capability', 'edit_posts' );
164 }
165
166 /**
167 * Assigns free units to a booking right after the booking engine stored its own meta.
168 *
169 * Hooked on the meta write instead of `save_post` because the booking engine inserts the
170 * post first and the serialized meta afterwards, so on `save_post` the dates are not
171 * available yet.
172 *
173 * @param int $meta_id Unused.
174 * @param int $post_id Booking post ID.
175 * @param string $meta_key Meta key being written.
176 * @param mixed $meta_value Unused.
177 */
178 public function maybe_auto_assign( $meta_id, $post_id, $meta_key, $meta_value ) {
179
180 if ( 'eshb_booking_metaboxes' !== $meta_key ) {
181 return;
182 }
183
184 if ( ! ESHB_PMS::get_option( 'auto_assign', 0 ) ) {
185 return;
186 }
187
188 if ( 'eshb_booking' !== get_post_type( $post_id ) ) {
189 return;
190 }
191
192 // The row we may have cached earlier in this request is the pre-write one.
193 ESHB_PMS_Assignment::flush_cache();
194
195 // Never overwrite a choice made by a human: only empty slots get filled.
196 ESHB_PMS_Assignment::auto_assign( (int) $post_id );
197 }
198
199 /**
200 * Drops the module meta when a booking is permanently deleted.
201 *
202 * @param int $post_id Post ID being deleted.
203 */
204 public function cleanup_booking_meta( $post_id ) {
205
206 if ( 'eshb_booking' === get_post_type( $post_id ) ) {
207 delete_post_meta( $post_id, ESHB_PMS_ASSIGN_META );
208 }
209 }
210 }
211
212 ESHB_PMS::instance();
213