/** * @return mixed */ private function _identify($credentials) { if ($this->check_session()) { $this->close_session(); } if (isset($credentials['user'], $credentials['pass'])) { // Table structure $arch =& $this->cfg['arch']; // Database Query if ($d = $this->db->rselect($this->cfg['tables']['users'], $this->fields, \bbn\tools::merge_arrays($this->cfg['conditions'], [$arch['users']['status'] => 1], [$arch['users']['login'] => $credentials['user']]))) { $this->id = $d['id']; $this->_user_info($d); // Canceling authentication if num_attempts > max_attempts if (!$this->check_attempts()) { $this->error = 4; } $pass = $this->db->select_one($this->cfg['tables']['passwords'], $arch['passwords']['pass'], [$arch['passwords']['id_user'] => $this->id], [$arch['passwords']['added'] => 'DESC']); if ($this->_check_password($credentials['pass'], $pass)) { $this->auth = 1; $this->_login(); } else { $this->record_attempt(); $this->error = 6; } } else { $this->error = 6; } } return $this->auth; }
/** * Returns an array containing any of the various components of the URL that are present. * * <code> * \bbn\str\text::parse_url('http://localhost/phpmyadmin/?db=test&table=users&server=1&target=&token=e45a102c5672b2b4fe84ae75d9148981'); * /*Returns [ * 'scheme' => 'http', * 'host' => 'localhost', * 'path' => '/phpmyadmin/', * 'query' => 'db=test&table=users&server=1&target=&token=e45a102c5672b2b4fe84ae75d9148981', * 'url' => 'http://localhost/phpmyadmin/', * 'params' => [ * 'db' => 'test', * 'table' => 'users', * 'server' => '1', * 'target' => '', * 'token' => 'e45a102c5672b2b4fe84ae75d9148981', * ], * ] * * </code> * * @param string $url The url. * * @return array */ public static function parse_url($url) { $url = self::cast($url); $r = \bbn\tools::merge_arrays(parse_url($url), ['url' => $url, 'query' => '', 'params' => []]); if (strpos($url, '?') > 0) { $p = explode('?', $url); $r['url'] = $p[0]; $r['query'] = $p[1]; $ps = explode('&', $r['query']); foreach ($ps as $p) { $px = explode('=', $p); $r['params'][$px[0]] = $px[1]; } } return $r; }
public static function sync(\bbn\db\connection $db, $dbs = '', $dbs_table = '', $num_try = 0) { if (!$num_try) { self::define($dbs, $dbs_table); self::first_call(); self::disable(); $mode_db = self::$db->get_error_mode(); $mode_dbs = self::$dbs->get_error_mode(); self::$db->set_error_mode("continue"); self::$dbs->set_error_mode("continue"); } $num_try++; $to_log = ['deleted_sync' => 0, 'deleted_real' => 0, 'updated_sync' => 0, 'updated_real' => 0, 'inserted_sync' => 0, 'inserted_real' => 0, 'num_problems' => 0, 'problems' => []]; $retry = false; $start = ($test = self::$dbs->get_one("\n SELECT MIN(moment)\n FROM " . self::$dbs->escape(self::$dbs_table) . "\n WHERE db NOT LIKE ?\n AND state = 0", self::$db->current)) ? $test : date('Y-m-d H:i:s'); // Deleting the entries prior to this sync we produced and have been seen by the twin process $to_log['deleted_sync'] = self::$dbs->delete(self::$dbs_table, [['db', 'LIKE', self::$db->current], ['state', '=', 1], ['moment', '<', $start]]); // Selecting the entries inserted $ds = self::$dbs->rselect_all(self::$dbs_table, ['id', 'tab', 'vals', 'moment'], [['db', 'NOT LIKE', self::$db->current], ['state', '=', 0], ['action', 'LIKE', 'insert']], ['moment' => 'ASC', 'id' => 'ASC']); // They just have to be inserted foreach ($ds as $i => $d) { if (isset(self::$methods['cbf1'])) { self::cbf1($d); } $vals = json_decode($d['vals'], 1); if (!is_array($vals)) { $to_log['num_problems']++; array_push($to_log['problems'], "Hey, look urgently at the row {$d['id']}!"); } else { if (self::$db->insert($d['tab'], $vals)) { if (isset(self::$methods['cbf2'])) { self::cbf2($d); } $to_log['inserted_sync']++; self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]); } else { if (self::$db->select($d['tab'], [], $vals)) { self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]); } else { if ($num_try > self::$max_retry) { $to_log['num_problems']++; array_push($to_log['problems'], "Problem while syncing (insert), check data with status 5 and ID " . $d['id']); self::$dbs->update(self::$dbs_table, ["state" => 5], ["id" => $d['id']]); } $retry = 1; } } } } // Selecting the entries modified and deleted in the twin DB, // ordered by table and rows (so the same go together) $ds = self::$dbs->rselect_all(self::$dbs_table, ['id', 'tab', 'action', 'rows', 'vals', 'moment'], [['db', 'NOT LIKE', self::$db->current], ['state', '=', 0], ['rows', 'NOT LIKE', '[]'], ['action', 'NOT LIKE', 'insert']], ['tab' => 'ASC', 'rows' => 'ASC', 'moment' => 'ASC', 'id' => 'ASC']); foreach ($ds as $i => $d) { // Executing the first callback if (isset(self::$methods['cbf1'])) { self::cbf1($d); } // Proceeding to the actions: delete is before if ($d['action'] === 'delete') { if (self::$db->delete($d['tab'], json_decode($d['rows'], 1))) { self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]); $to_log['deleted_real']++; } else { if (!self::$db->select($d['tab'], [], json_decode($d['rows'], 1))) { self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]); } else { if ($num_try > self::$max_retry) { self::$dbs->update(self::$dbs_table, ["state" => 5], ["id" => $d['id']]); $to_log['num_problems']++; array_push($to_log['problems'], "Problem while syncing (delete), check data with status 5 and ID " . $d['id']); } $retry = 1; } } } // Checking if there is another change done to this record and when in the twin DB $next_time = isset($ds[$i + 1]) && $ds[$i + 1]['tab'] === $d['tab'] && $ds[$i + 1]['rows'] === $d['rows'] ? $ds[$i + 1]['moment'] : date('Y-m-d H:i:s'); // Looking for the actions done on this specific record in our database // between the twin change and the next (or now if there is no other change) $each = self::$dbs->rselect_all(self::$dbs_table, ['id', 'moment', 'action', 'vals'], [['db', 'LIKE', self::$db->current], ['tab', 'LIKE', $d['tab']], ['rows', 'LIKE', $d['rows']], ['moment', '>=', $d['moment']], ['moment', '<', $next_time]]); if (count($each) > 0) { $to_log['num_problems']++; array_push($to_log['problems'], "Conflict!", $d); foreach ($each as $i => $e) { // If it's deleted locally and updated on the twin we restore if ($e['action'] === 'delete') { if ($d['action'] === 'update') { if (!self::$db->insert_update($d['tab'], \bbn\tools::merge_arrays(json_decode($e['vals'], 1), json_decode($d['vals'], 1)))) { $to_log['num_problems']++; array_push($to_log['problems'], "insert_update number 1 had a problem"); } } } else { if ($e['action'] === 'update') { if ($d['action'] === 'delete') { if (!self::$db->insert_update($d['tab'], \bbn\tools::merge_arrays(json_decode($d['vals'], 1), json_decode($e['vals'], 1)))) { $to_log['num_problems']++; array_push($to_log['problems'], "insert_update had a problem"); } } else { if ($d['action'] === 'update') { $d['vals'] = json_encode(\bbn\tools::merge_arrays(json_decode($d['vals'], 1), json_decode($e['vals'], 1))); } } } } } } // Proceeding to the actions update is after in case we needed to restore if ($d['action'] === 'update') { if (self::$db->update($d['tab'], json_decode($d['vals'], 1), json_decode($d['rows'], 1))) { self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]); $to_log['updated_real']++; } else { if (self::$db->select($d['tab'], [], \bbn\tools::merge_arrays(json_decode($d['rows'], 1), json_decode($d['vals'], 1)))) { self::$dbs->update(self::$dbs_table, ["state" => 1], ["id" => $d['id']]); } else { if ($num_try > self::$max_retry) { self::$dbs->update(self::$dbs_table, ["state" => 5], ["id" => $d['id']]); $to_log['num_problems']++; array_push($to_log['problems'], "Problem while syncing (update), check data with status 5 and ID " . $d['id']); } $retry = 1; } } } // Callback number 2 if (isset(self::$methods['cbf2'])) { self::cbf2($d); } } $res = []; foreach ($to_log as $k => $v) { if (!empty($v)) { $res[$k] = $v; } } if ($retry && $num_try <= self::$max_retry) { $res = \bbn\tools::merge_arrays($res, self::sync($db, $dbs, $dbs_table, $num_try)); } else { self::$db->set_error_mode($mode_db); self::$dbs->set_error_mode($mode_dbs); self::enable(); } return $res; }
/** * Generates a whole input configuration array by combining the passed and default configurations * @param array $cfg The input's config * @return array */ public function input($cfg = array()) { if (is_array($cfg) && isset($cfg['attr']['name'])) { self::give_id($cfg); if (isset($cfg['field'])) { $cfg = \bbn\tools::merge_arrays(self::specs('fields', $cfg['field']), $cfg); } /* if ( !isset($cfg['tag']) ){ $cfg['tag'] = 'input'; } if ( !isset($cfg['attr']['type']) ){ $cfg['attr']['type'] = 'text'; } */ if (isset($cfg['data'])) { if (isset($cfg['data']['sql'], $this->_current_cfg['data']['db'])) { $db =& $this->_current_cfg['data']['db']; if (!isset($cfg['widget']['options']['dataSource'])) { $cfg['widget']['options']['dataSource'] = []; } $count = ($r = $db->query($cfg['data']['sql'])) ? $r->count() : 0; if ($count <= self::max_values_at_once) { if ($ds = $db->get_irows($cfg['data']['sql'])) { foreach ($ds as $d) { if (count($d) > 1) { array_push($cfg['widget']['options']['dataSource'], ['value' => $d[0], 'text' => $d[1]]); } else { array_push($cfg['widget']['options']['dataSource'], $d[0]); } } } } else { $cfg['field'] = 'autocomplete'; } } else { if (is_array($cfg['data']) && count($cfg['data']) > 0) { if (isset($cfg['data'][0])) { $cfg['widget']['options']['dataSource'] = $cfg['data']; } else { $cfg['widget']['options']['dataSource'] = []; foreach ($cfg['data'] as $k => $v) { array_push($cfg['widget']['options']['dataSource'], ['value' => $k, 'text' => $v]); } } } } if (isset($cfg['widget']['options']['dataSource'][0]['text'])) { $cfg['widget']['options']['dataTextField'] = 'text'; $cfg['widget']['options']['dataValueField'] = 'value'; } } if (is_array($cfg)) { // Size calculation if (isset($cfg['attr']['maxlength']) && !isset($cfg['attr']['size'])) { if ($cfg['attr']['maxlength'] <= 20) { $cfg['attr']['size'] = (int) $cfg['attr']['maxlength']; } } if (isset($cfg['attr']['size'], $cfg['attr']['minlength']) && $cfg['attr']['size'] < $cfg['attr']['minlength']) { $cfg['attr']['size'] = (int) $cfg['attr']['minlength']; } $cfg = array_filter($cfg, function ($a) { return !(is_array($a) && count($a) === 0); }); } if (isset($cfg['null']) && $cfg['null']) { if (empty($cfg['attr']['value'])) { $cfg['attr']['value'] = null; $cfg['attr']['disabled'] = true; if (isset($cfg['widget'])) { if (!isset($cfg['script'])) { $cfg['script'] = ''; } /* $cfg['script'] .= 'if ( $("#'.$cfg['attr']['id'].'").data("'.$cfg['widget']['name'].'") ){ $("#'.$cfg['attr']['id'].'").data("'.$cfg['widget']['name'].'").enable(false); } else if ( $("#'.$cfg['attr']['id'].'").'.$cfg['widget']['name'].' ){ $("#'.$cfg['attr']['id'].'").'.$cfg['widget']['name'].'("enable", false); }'; * */ } } } $t = new \bbn\html\input($cfg); return $t; } return false; }