-
diff --git a/event/migrations/all.php b/event/migrations/all.php
deleted file mode 100644
index d387706..0000000
--- a/event/migrations/all.php
+++ /dev/null
@@ -1,15 +0,0 @@
-
diff --git a/event/generate_qr.php b/src/generate_qr.php
similarity index 65%
rename from event/generate_qr.php
rename to src/generate_qr.php
index ad00174..66df927 100644
--- a/event/generate_qr.php
+++ b/src/generate_qr.php
@@ -1,7 +1,10 @@
-
+
diff --git a/event/lib/attendance.php b/src/lib/attendance-old.php
similarity index 100%
rename from event/lib/attendance.php
rename to src/lib/attendance-old.php
diff --git a/src/lib/attendance.php b/src/lib/attendance.php
new file mode 100644
index 0000000..6f7f688
--- /dev/null
+++ b/src/lib/attendance.php
@@ -0,0 +1,220 @@
+person = $person;
+ $this->eventSession = $eventSession;
+
+ if ($logTime === null) {
+ $this->logTime = new DateTime();
+ } else {
+ $this->logTime = $logTime;
+ }
+ $this->id = $id;
+ }
+
+ /**
+ * List all attendance records.
+ *
+ * @return array An array of Attendance objects.
+ */
+ public static function list(): array {
+ // Connect to the database (replace with your actual connection logic)
+ $db = get_db();
+
+ // Perform a query to retrieve all attendance records
+ $query = "SELECT * FROM attendance";
+ $result = $db->query($query);
+
+ $attendanceList = [];
+
+ // Fetch the results and create Attendance objects
+ while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
+ $attendanceList[] = Attendance::get([
+ "id" => intval($row['id'])
+ ]);
+ }
+
+ // Close the database connection
+ $db->close();
+
+ return $attendanceList;
+ }
+
+ /**
+ * Get an attendance record by ID.
+ *
+ * @param array $data
+ * @return Attendance|null An Attendance object or null if not found.
+ */
+ public static function get(array $data): ?Attendance {
+ // Connect to the database (replace with your actual connection logic)
+ $db = get_db();
+
+ $query = "
+ SELECT * FROM attendance
+ WHERE 1=1";
+
+ // Iterate over the data dictionary
+ foreach ($data as $key => $value) {
+ // Escape the values to prevent SQL injection (assuming using SQLite3 class)
+ $escapedValue = $db->escapeString($value);
+
+ // Add the key-value pair to the WHERE clause
+ $query .= " AND $key='$escapedValue'";
+ }
+
+ // Execute the statement
+ $result = $db->query($query);
+ $row = $result->fetchArray(SQLITE3_ASSOC);
+
+ if ($row === false) {
+ // No matching record found
+ return null;
+ }
+
+ $person = Person::get([
+ "id" => $row['person_id']
+ ]);
+ $event_session = EventSession::get([
+ "id" => $row['event_session_id']
+ ]);
+
+ $attendance = new Attendance(
+ $person,
+ $event_session,
+ new DateTime($row['log_time']),
+ intval($row['id'])
+ );
+
+ // Close the database connection
+ $db->close();
+
+ return $attendance;
+ }
+
+ public static function log(
+ Person $person,
+ EventSession $eventSession
+ ): Attendance {
+ $attendance = new Attendance($person, $eventSession, new DateTime());
+ return $attendance->insert();
+ }
+
+ public function insert(): Attendance
+ {
+ $this->validate();
+
+ $db = get_db(); // Assuming get_db returns a database connection
+
+ // Prepare the SQL statement
+ $personId = $this->person->id;
+ $sessionId = $this->eventSession->id;
+ $logTime = $this->logTime->format('Y-m-d H:i:s');
+ $insertQuery = "
+ INSERT INTO attendance (
+ person_id, event_session_id, log_time
+ ) VALUES (
+ $personId,
+ $sessionId,
+ '$logTime'
+ )";
+ $db->exec($insertQuery);
+ // Get the last inserted ID
+ $lastInsertID = $db->lastInsertRowID();
+
+ // Close the database connection
+ $db->close();
+
+ return Attendance::get(["id" => $lastInsertID]);
+ }
+
+ /**
+ * Validate the attendance data.
+ *
+ * @throws Exception If validation fails.
+ */
+ public function validate(): bool
+ {
+ if ($this->person == null) {
+ throw new Exception("Person is required.");
+ }
+
+ if (!$this->person->id) {
+ throw new Exception("Person is invalid.");
+ }
+
+ if ($this->eventSession == null) {
+ throw new Exception("Event Session is required.");
+ }
+
+ if (!$this->eventSession->id) {
+ throw new Exception("Event Session is invalid.");
+ }
+
+ $currentDateTime = new DateTime();
+
+ // Check if the current date and time is within the event session's interval
+ if (
+ $currentDateTime < $this->eventSession->startDate
+ || $currentDateTime > $this->eventSession->endDate
+ ) {
+ throw new Exception(
+ "Attendance (" . $currentDateTime->format('Y-m-d H:i:s')
+ . ") is not allowed outside the event session ("
+ . $this->eventSession->startDate->format('Y-m-d H:i:s')
+ . " - "
+ . $this->eventSession->endDate->format('Y-m-d H:i:s')
+ . ")"
+
+ );
+ }
+
+ // Check if it's the first session of the event
+ $firstSession = $this->eventSession->isFirstSession(); // Implement this method
+
+ if (!$firstSession) {
+ // If it's not the first session, check if the person attended previous sessions
+ $previousSessions = $this->eventSession->getPreviousSessions(); // Implement this method
+
+ foreach ($previousSessions as $previousSession) {
+ // Check if the person attended each previous session
+ if (!$this->attendedSession($this->person, $previousSession)) { // Implement this method
+ throw new Exception("Attendance is not allowed. Please attend previous sessions.");
+ }
+ }
+ }
+
+
+ return true;
+ }
+
+ public static function attendedSession(
+ Person $person, EventSession $eventSession
+ ): bool {
+ $attendance = Attendance::get([
+ "person_id" => $person->id,
+ "event_session_id" => $eventSession->id
+ ]);
+
+ return $attendance !== null;
+ }
+}
+
+?>
diff --git a/event/lib/db.php b/src/lib/db.php
similarity index 100%
rename from event/lib/db.php
rename to src/lib/db.php
diff --git a/event/lib/dotenv.php b/src/lib/dotenv.php
similarity index 100%
rename from event/lib/dotenv.php
rename to src/lib/dotenv.php
diff --git a/event/lib/email.php b/src/lib/email.php
similarity index 90%
rename from event/lib/email.php
rename to src/lib/email.php
index 923e046..c6d32f8 100644
--- a/event/lib/email.php
+++ b/src/lib/email.php
@@ -1,5 +1,7 @@
$context
*/
@@ -12,7 +14,9 @@ function send_email(
string $reply_to,
string $cc
): bool {
- // $templateFile = dirname(__DIR__) . '/templates/subscription-email.html';
+ if (get_env("SEND_EMAIL") == "0") {
+ return false;
+ }
$htmlContent = file_get_contents($templateFile);
foreach ($context as $key => $value) {
diff --git a/src/lib/event.php b/src/lib/event.php
new file mode 100644
index 0000000..8cf2425
--- /dev/null
+++ b/src/lib/event.php
@@ -0,0 +1,350 @@
+name = $name;
+ $this->description = $description;
+ $this->startDate = $startDate;
+ $this->endDate = $endDate;
+ $this->id = $id;
+ }
+
+ /**
+ * @param array $data
+ */
+ public static function get(array $data): ?EventSangha {
+ $db = get_db();
+
+ $query = "SELECT * FROM event WHERE 1=1";
+
+ foreach ($data as $key => $value) {
+ $escapedValue = $db->escapeString($value);
+ $query .= " AND $key='$escapedValue'";
+ }
+
+ $result = $db->query($query);
+
+ if (!$result) {
+ return null;
+ }
+
+ $row = $result->fetchArray(SQLITE3_ASSOC);
+
+ if ($row === false) {
+ return null;
+ }
+
+ return new EventSangha(
+ $row['name'],
+ $row['description'],
+ new DateTime($row['start_date']),
+ new DateTime($row['end_date']),
+ intval($row['id'])
+ );
+ }
+
+ /**
+ * @param array $filters
+ * @return array
+ */
+ public static function list(array $filters = []): array {
+ $db = get_db();
+ $query = "SELECT * FROM event WHERE 1=1";
+
+ foreach ($filters as $key => $value) {
+ $escapedValue = $db->escapeString($value);
+ $query .= " AND $key='$escapedValue'";
+ }
+ $result = $db->query($query);
+
+ if (!$result) {
+ return [];
+ }
+
+ $event_list = [];
+
+ while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
+ $event_list[] = EventSangha::get(["id" => $row['id']]);
+ }
+
+ return $event_list;
+ }
+
+ public function insert(): EventSangha {
+ $db = get_db();
+
+ $startDateStr = $this->startDate->format('Y-m-d H:i:s');
+ $endDateStr = $this->endDate->format('Y-m-d H:i:s');
+
+ $insertQuery = "
+ INSERT INTO event (name, description, start_date, end_date)
+ VALUES (
+ '$this->name',
+ '$this->description',
+ '$startDateStr',
+ '$endDateStr'
+ )";
+ $db->exec($insertQuery);
+ $lastInsertID = $db->lastInsertRowID();
+ $db->close();
+
+ return EventSangha::get(["id" => $lastInsertID]);
+ }
+
+ public function update(): EventSangha {
+ $db = get_db();
+ $startDateStr = $this->startDate->format('Y-m-d H:i:s');
+ $endDateStr = $this->endDate->format('Y-m-d H:i:s');
+
+ if (!$this->id) {
+ throw new Exception("This event is not registered yet.");
+ }
+
+ $insertQuery = "
+ UPDATE event
+ SET
+ name='$this->name',
+ description='$this->description',
+ start_date='$startDateStr',
+ end_date='$endDateStr'
+ WHERE id=$this->id";
+ $db->exec($insertQuery);
+
+ return $this;
+ }
+
+ public function save(): EventSangha {
+ if ($this->id !== null) {
+ return $this->update();
+ } else {
+ return $this->insert();
+ }
+ }
+
+ /**
+ * @return array
+ */
+ public function getSessions(): array {
+ return EventSession::list([
+ "event_id" => $this->id
+ ]);
+ }
+
+ public function getFirstSession(): ?EventSession {
+ // Retrieve the first session of the event
+ // Assuming $eventSessions is an array of EventSession objects for this event
+ $eventSessions = $this->getSessions();
+
+ if (empty($eventSessions)) {
+ return null; // No sessions for this event
+ }
+
+ // Sort sessions by start date (you may need to modify this depending on your data)
+ usort($eventSessions, function ($a, $b) {
+ return $a->startDate <=> $b->startDate;
+ });
+
+ return $eventSessions[0];
+ }
+}
+
+class EventSession {
+ public ?int $id;
+ public EventSangha $event;
+ public string $name;
+ public DateTime $startDate;
+ public DateTime $endDate;
+
+ function __construct(
+ EventSangha $event,
+ string $name,
+ DateTime $startDate,
+ DateTime $endDate,
+ ?int $id = null
+ ) {
+ $this->event = $event;
+ $this->name = $name;
+ $this->startDate = $startDate;
+ $this->endDate = $endDate;
+ $this->id = $id;
+ }
+
+ /**
+ * @param array $data
+ */
+ public static function get(array $data): ?EventSession {
+ $db = get_db();
+
+ $query = "SELECT * FROM event_session WHERE 1=1";
+
+ foreach ($data as $key => $value) {
+ $escapedValue = $db->escapeString($value);
+ $query .= " AND $key='$escapedValue'";
+ }
+
+ $result = $db->query($query);
+
+ $row = $result->fetchArray(SQLITE3_ASSOC);
+
+ if ($row === false) {
+ return null;
+ } else {
+ // Fetch the associated EventSangha
+ $eventId = intval($row['event_id']);
+ $event = EventSangha::get(['id' => $eventId]);
+
+ $eventSession = new EventSession(
+ $event,
+ $row['name'],
+ new DateTime($row['start_date']),
+ new DateTime($row['end_date']),
+ intval($row['id'])
+ );
+
+ return $eventSession;
+ }
+ }
+
+ /**
+ * @param array $filters
+ * @return array
+ */
+ public static function list(array $filters = []): array {
+ $db = get_db();
+ $query = "SELECT * FROM event_session WHERE 1=1";
+
+ foreach ($filters as $key => $value) {
+ $escapedValue = $db->escapeString($value);
+ $query .= " AND $key='$escapedValue'";
+ }
+
+ $result = $db->query($query);
+
+ $eventSessions = [];
+
+ while ($row = $result->fetchArray(SQLITE3_ASSOC)) {
+ // Fetch the associated EventSangha
+ $eventId = intval($row['event_id']);
+ $event = EventSangha::get(['id' => $eventId]);
+
+ $eventSession = new EventSession(
+ $event,
+ $row['name'],
+ new DateTime($row['start_date']),
+ new DateTime($row['end_date']),
+ intval($row['id'])
+ );
+
+ $eventSessions[] = $eventSession;
+ }
+
+ return $eventSessions;
+ }
+
+ function validate(): bool {
+ if (empty($this->name)) {
+ throw new Exception("Event session name is required.");
+ }
+
+ if ($this->startDate >= $this->endDate) {
+ throw new Exception("Event session end date should be after the start date.");
+ }
+
+ return true;
+ }
+
+ function insert(): EventSession {
+ $this->validate();
+
+ $db = get_db();
+ $insertQuery = "INSERT INTO event_session (event_id, name, start_date, end_date)
+ VALUES (
+ {$this->event->id},
+ '$this->name',
+ '{$this->startDate->format('Y-m-d H:i:s')}',
+ '{$this->endDate->format('Y-m-d H:i:s')}'
+ )";
+
+ $db->exec($insertQuery);
+ $lastInsertID = $db->lastInsertRowID();
+ $this->id = $lastInsertID;
+
+ $eventSession = EventSession::get(["id" => $lastInsertID]);
+
+ if ($eventSession === null) {
+ throw new Exception("The new event session is not available yet in the database.");
+ }
+
+ return $eventSession;
+ }
+
+ function update(): EventSession {
+ $this->validate();
+
+ if (!$this->id) {
+ throw new Exception("This event session is not registered yet.");
+ }
+
+ $db = get_db();
+ $updateQuery = "UPDATE event_session
+ SET
+ event_id = {$this->event->id},
+ name = '$this->name',
+ start_date = '{$this->startDate->format('Y-m-d H:i:s')}',
+ end_date = '{$this->endDate->format('Y-m-d H:i:s')}'
+ WHERE id = {$this->id}";
+
+ $db->exec($updateQuery);
+
+ return $this;
+ }
+
+ function save(): EventSession {
+ if ($this->id) {
+ return $this->update();
+ }
+
+ return $this->insert();
+ }
+
+ public function isFirstSession(): bool {
+ $firstSession = $this->event->getFirstSession();
+ return $this->id === $firstSession->id;
+ }
+
+ /**
+ * @return array
+ */
+ public function getPreviousSessions(): array {
+ // Retrieve all previous sessions of the same event
+ $event = $this->event;
+ $eventSessions = $event->getSessions();
+
+ $previousSessions = [];
+
+ foreach ($eventSessions as $session) {
+ if ($session->startDate < $this->startDate) {
+ $previousSessions[] = $session;
+ }
+ }
+
+ return $previousSessions;
+ }
+}
+
+?>
diff --git a/event/lib/person.php b/src/lib/person.php
similarity index 100%
rename from event/lib/person.php
rename to src/lib/person.php
diff --git a/event/lib/qr.php b/src/lib/qr.php
similarity index 100%
rename from event/lib/qr.php
rename to src/lib/qr.php
diff --git a/event/lib/settings.php b/src/lib/settings.php
similarity index 81%
rename from event/lib/settings.php
rename to src/lib/settings.php
index 122a4b2..8a886ee 100644
--- a/event/lib/settings.php
+++ b/src/lib/settings.php
@@ -7,7 +7,10 @@ function get_env(string $key, string $default = ""): string {
$env_default = [
'HOST_ADDRESS' => 'https://rinchen.org/event-retiro',
+ 'SEND_EMAIL' => "1",
];
return $env[$key] ?? $env_default[$key] ?? $default;
}
+
+$BASE_URL = get_env("HOST_ADDRESS");
diff --git a/event/lib/subscription.php b/src/lib/subscription.php
similarity index 100%
rename from event/lib/subscription.php
rename to src/lib/subscription.php
diff --git a/event/migrations/0001.php b/src/migrations/0001.php
similarity index 90%
rename from event/migrations/0001.php
rename to src/migrations/0001.php
index 79bf3bb..47a1dc9 100644
--- a/event/migrations/0001.php
+++ b/src/migrations/0001.php
@@ -46,7 +46,10 @@ function attendance_table(): void {
$db->close();
}
+function migrate_0001(): void {
+ person_table();
+ subscription_table();
+ attendance_table();
+}
-person_table();
-subscription_table();
-attendance_table();
+migrate_0001();
diff --git a/event/migrations/0002.php b/src/migrations/0002.php
similarity index 81%
rename from event/migrations/0002.php
rename to src/migrations/0002.php
index b2fc63a..e7fc596 100644
--- a/event/migrations/0002.php
+++ b/src/migrations/0002.php
@@ -24,5 +24,9 @@ function subscription_add_active_column(): void {
$db->close();
}
-person_add_active_column();
-subscription_add_active_column();
+function migrate_0002(): void {
+ person_add_active_column();
+ subscription_add_active_column();
+}
+
+migrate_0002();
diff --git a/src/migrations/0003.php b/src/migrations/0003.php
new file mode 100644
index 0000000..4b1ff87
--- /dev/null
+++ b/src/migrations/0003.php
@@ -0,0 +1,72 @@
+exec($createQuery);
+ $db->close();
+}
+
+function event_session_create_table(): void {
+ $db = get_db();
+
+ // Create the 'event_session' table
+ $createQuery = "
+ CREATE TABLE IF NOT EXISTS event_session (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ event_id INTEGER NOT NULL,
+ name TEXT NOT NULL,
+ start_date DATETIME NOT NULL,
+ end_date DATETIME NOT NULL
+ )
+ ";
+
+ $db->exec($createQuery);
+ $db->close();
+}
+
+function modify_attendance_table(): void {
+ // Connect to the SQLite database
+ $db = get_db();
+
+ // Modify the attendance_table if it exists
+ $query = "ALTER TABLE attendance RENAME TO temp_attendance";
+ $db->exec($query);
+
+ // Create the modified attendance table
+ $query = "CREATE TABLE IF NOT EXISTS attendance (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ person_id INTEGER,
+ event_session_id INTEGER,
+ log_time TEXT
+ )";
+ $db->exec($query);
+
+ // Drop the temporary table
+ $query = "DROP TABLE temp_attendance";
+ $db->exec($query);
+
+ $db->close();
+}
+
+
+function migrate_0003(): void {
+ event_create_table();
+ event_session_create_table();
+ modify_attendance_table();
+}
+
+migrate_0003();
diff --git a/src/migrations/all.php b/src/migrations/all.php
new file mode 100644
index 0000000..75ebe37
--- /dev/null
+++ b/src/migrations/all.php
@@ -0,0 +1,12 @@
+ $personId]);
+ $eventSession = EventSession::get(["id" => $eventSessionId]);
+
+ // Log the attendance
+ try {
+ Attendance::log($person, $eventSession);
+ echo '
Attendance logged successfully!
';
+ } catch (Exception $e) {
+ echo '
' . $e->getMessage() . '
';
+ }
+}
+
+// Retrieve data for the dropdowns
+$personList = Person::list();
+$eventList = EventSangha::list();
+$eventSessionList = EventSession::list();
+
+?>
+
+
Attendance Log
+
+
+
+Back to the menu
+Back to the List
+
+
diff --git a/src/templates/attendance/list.php b/src/templates/attendance/list.php
new file mode 100644
index 0000000..a8bae0f
--- /dev/null
+++ b/src/templates/attendance/list.php
@@ -0,0 +1,49 @@
+
+
+
+
+ Lista de asistencia
+
+
+
+
+
+
+
+ Back to the menu
+ Back to the list
+
diff --git a/src/templates/event-session/list.php b/src/templates/event-session/list.php
new file mode 100644
index 0000000..bb10673
--- /dev/null
+++ b/src/templates/event-session/list.php
@@ -0,0 +1,49 @@
+
+
-
+
-<< Back to the menu
+Back to the menu
+Back to the list
diff --git a/event/subscription_list.php b/src/templates/subscription/list.php
similarity index 90%
rename from event/subscription_list.php
rename to src/templates/subscription/list.php
index ab51545..5d83cf5 100644
--- a/event/subscription_list.php
+++ b/src/templates/subscription/list.php
@@ -1,6 +1,6 @@