You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
299 lines
8.5 KiB
299 lines
8.5 KiB
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace tts\database;
|
|
|
|
final class help_save {
|
|
|
|
use run_sql;
|
|
use validation;
|
|
|
|
const successful_save = 1;
|
|
const duplicate_found = 2;
|
|
const validation_error = 3;
|
|
const pre_save_failed = 4;
|
|
const post_save_failed = 5;
|
|
|
|
private $table;
|
|
private $members = [];
|
|
private $validation_members = [];
|
|
private $missing = [];
|
|
private $error_message;
|
|
private $pdo;
|
|
private $primary_key = 'id';
|
|
|
|
public function __construct($pdo, $table) {
|
|
$this->pdo = $pdo;
|
|
$this->table = $table;
|
|
}
|
|
|
|
public function saved(bool $worked = true): bool {
|
|
if (headers_sent()) {
|
|
return false;
|
|
}
|
|
header("Content-Type: application/json; charset=UTF-8");
|
|
$time = \tts\time_zones::convert_time_zone(array('format' => 'g:i a'));
|
|
echo json_encode(['time' => $time, 'saved' => $worked]);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* JSON API inform AJAX that save failed
|
|
*/
|
|
public function save_failed($msg = 'Save Failed!'): void {
|
|
\tts\api::error(array('code' => 500, 'success' => false, 'error' => $msg, 'responce' => \tts\api::INTERNAL_ERROR));
|
|
}
|
|
|
|
public function dump_table_fields(string $table) {
|
|
$fields = $this->get_fields($table);
|
|
$this->do_dump($fields);
|
|
}
|
|
|
|
public function dump_diff(): bool {
|
|
$fields = $this->get_fields($this->table);
|
|
|
|
$diff = array_diff($fields, array_keys($this->members));
|
|
|
|
if (($key = array_search('id', $diff)) !== false) {
|
|
unset($diff[$key]); // Who cares about IDs
|
|
}
|
|
|
|
if (count($diff)) {
|
|
echo "Diff on fields:<br>" . PHP_EOL;
|
|
$this->do_dump($diff);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private function do_dump(array $data) {
|
|
echo "<pre style=\"border: 1px solid #000; overflow: auto; margin: 0.5em;\">";
|
|
print_r($data);
|
|
echo '</pre>';
|
|
}
|
|
|
|
public function set_primary_key_name(string $key): void {
|
|
$this->primary_key = $key;
|
|
}
|
|
|
|
/**
|
|
* @param array $data [fields=[key=>value]]
|
|
*/
|
|
public function set_members_by_array(array $data): bool {
|
|
$error_count = (isset($data['errors'])) ? count($data['errors']) : 0;
|
|
if ($error_count) {
|
|
return false;
|
|
}
|
|
|
|
if (count($data['meta']['missing'])) {
|
|
$this->missing = $data['meta']['missing'];
|
|
}
|
|
|
|
if (count($data['fields'])) {
|
|
foreach($data['fields'] as $key => $value) {
|
|
$meta = $data['meta'][$key] ?? false;
|
|
if ($meta !== false) {
|
|
$skip_db = $meta['skip_db'] ?? false;
|
|
if ($skip_db === true) {
|
|
continue; // Skip Field
|
|
}
|
|
}
|
|
$this->members[$key] = $value;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function auto_set_members(array $post = [], array $skip = ['route', 'm'], array $only_these = []): void {
|
|
if (isset($post['json'])) {
|
|
$globals = \tts\safer_io::get_json_post_data();
|
|
} else {
|
|
$json_post = count($post);
|
|
$globals = ($json_post) ? $post : filter_input_array(INPUT_POST) ?? [];
|
|
}
|
|
foreach ($globals as $key => $data) {
|
|
if (count($skip) && in_array($key, $skip)) {
|
|
continue;
|
|
}
|
|
if (in_array($key, $only_these) || !count($only_these)) {
|
|
$this->members[$key] = (\tts\request::is_not_empty($data)) ? $data : "";
|
|
}
|
|
}
|
|
}
|
|
|
|
public function get_missing() {
|
|
return $this->missing;
|
|
}
|
|
|
|
/* From old Model code: */
|
|
|
|
public function get_member(string $member) {
|
|
return $this->members[$member] ?? null;
|
|
}
|
|
|
|
public function get_members(string $member) {
|
|
return $this->members;
|
|
}
|
|
|
|
public function set_member(string $member, string $data): void {
|
|
$this->members[$member] = $data;
|
|
}
|
|
|
|
public function has_member($member): bool {
|
|
return isset($this->members[$member]);
|
|
}
|
|
|
|
public function get_last_error(): string {
|
|
return $this->error_message;
|
|
}
|
|
|
|
/**
|
|
* Set Member for Validation
|
|
* @param string $key
|
|
* @param array $a
|
|
*/
|
|
public function set_member_for_validation(string $key, array $a): void {
|
|
$this->validation_members[$key] = $a;
|
|
}
|
|
|
|
/**
|
|
* Get Validation Member
|
|
* @param string $key
|
|
* @return array
|
|
*/
|
|
public function get_vaildation_member(string $key): array {
|
|
return $this->validation_members[$key] ?? array();
|
|
}
|
|
|
|
/**
|
|
* Unset Validation Member
|
|
* @param string $key
|
|
*/
|
|
public function clear_validation_member(string $key): void {
|
|
unset($this->validation_members[$key]);
|
|
}
|
|
|
|
private function cleanup($bind) {
|
|
if (!is_array($bind)) {
|
|
if (!empty($bind)) {
|
|
$bind = array($bind);
|
|
} else {
|
|
$bind = array();
|
|
}
|
|
}
|
|
return $bind;
|
|
}
|
|
|
|
public function insert($table, $info) {
|
|
$fields = $this->filter($table, $info);
|
|
|
|
if (strrpos($table, "`") === false) {
|
|
$table = "`{$table}`";
|
|
}
|
|
|
|
$sql = "INSERT INTO {$table} (" . implode(", ", $fields) . ") VALUES (:" . implode(", :", $fields) . ");";
|
|
$bind = array();
|
|
foreach ($fields as $field) {
|
|
$bind[":$field"] = $info[$field];
|
|
}
|
|
return $this->run($sql, $bind);
|
|
}
|
|
|
|
public function update($table, $info, $where, $bind = "") {
|
|
$bind = $this->cleanup($bind);
|
|
$fields = $this->filter($table, $info);
|
|
|
|
if (strrpos($table, "`") === false) {
|
|
$table = "`{$table}`";
|
|
}
|
|
|
|
$sql = "UPDATE {$table} SET ";
|
|
$f = 0;
|
|
|
|
foreach ($fields as $key => $value) {
|
|
if ($f > 0) {
|
|
$sql .= ", ";
|
|
}
|
|
$f++;
|
|
|
|
$value = trim($value);
|
|
|
|
if (strrpos($value, "`") === false) {
|
|
$cf = '`' . $value . '`';
|
|
} else {
|
|
$cf = $value;
|
|
}
|
|
|
|
$sql .= $cf . " = :update_" . $value;
|
|
$bind[":update_$value"] = $info[$value];
|
|
}
|
|
|
|
$sql .= " WHERE " . $where . ";";
|
|
|
|
return $this->run($sql, $bind);
|
|
}
|
|
|
|
public static function make_db_time_stamp(): string {
|
|
return \tts\time_zones::convert_time_zone(['format' => 'database', 'timezone' => 'UTC']);
|
|
}
|
|
|
|
/**
|
|
* Save
|
|
*
|
|
* @param object $lcoal_model Should be $this from the Model
|
|
*
|
|
* Insert if primary key not set
|
|
* Update if primary key set
|
|
*/
|
|
public function save(object $local_model=null, bool $validate = true): int {
|
|
|
|
if (method_exists($local_model, 'pre_save')) {
|
|
$pre_was_successfull = $local_model->pre_save();
|
|
if (! $pre_was_successfull) {
|
|
return self::pre_save_failed;
|
|
}
|
|
}
|
|
$name = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); // Get DB Driver
|
|
if ($name === 'mysql' && $validate) {
|
|
if (!$this->validate_mysql()) {
|
|
return self::validation_error;
|
|
}
|
|
}
|
|
|
|
if ($this->has_member('modified')) {
|
|
$this->set_member('modified', self::make_db_time_stamp());
|
|
}
|
|
|
|
if (empty($this->members[$this->primary_key])) {
|
|
if (method_exists($local_model, 'duplicate_check')) {
|
|
$dup = $local_model->duplicate_check();
|
|
if ($dup) {
|
|
return self::duplicate_found;
|
|
}
|
|
}
|
|
|
|
if ($this->has_member('created')) {
|
|
$this->set_member('created', self::make_db_time_stamp());
|
|
}
|
|
|
|
$this->members[$this->primary_key] = $this->insert($this->table, $this->members);
|
|
} else {
|
|
$this->set_member("row_count", $this->update($this->table, $this->members,
|
|
"`{$this->primary_key}` = :search_key",
|
|
array(':search_key' => $this->members[$this->primary_key])
|
|
));
|
|
}
|
|
|
|
if (method_exists($local_model, 'post_save')) {
|
|
$post_save_successfull = $local_model->post_save();
|
|
if (! $post_save_successfull) {
|
|
return self::post_save_failed;
|
|
}
|
|
}
|
|
|
|
return self::successful_save;
|
|
}
|
|
|
|
/* End Model */
|
|
}
|
|
|