Пример #1
0
 /**
  * все сохранение делается внутри транзакции (включая beforeSave и afterSave), если будет исключение - транзакция будет откачена PDO
  */
 public function save()
 {
     ActiveRecordHelper::exceptionIfObjectIsIncompatibleWithActiveRecord($this);
     $obj_class_name = get_class($this);
     $obj_db_id = $obj_class_name::DB_ID;
     $transaction_is_my = false;
     if (!DBWrapper::inTransaction($obj_db_id)) {
         DBWrapper::beginTransaction($obj_db_id);
         $transaction_is_my = true;
     }
     $this->beforeSave();
     \OLOG\Model\ActiveRecordHelper::saveModelObj($this);
     // не вызываем afterSave если это вызов save для этого объекта изнутри aftersave этого же объекта (для предотвращения бесконечного рекурсивного вызова afterSave)
     static $__inprogress = [];
     $inprogress_key = FullObjectId::getFullObjectId($this);
     if (!array_key_exists($inprogress_key, $__inprogress)) {
         $__inprogress[$inprogress_key] = 1;
         $this->afterSave();
         unset($__inprogress[$inprogress_key]);
     }
     // комитим только если мы же и стартовали транзакцию (на случай вложенных вызовов)
     if ($transaction_is_my) {
         DBWrapper::commitTransaction($obj_db_id);
     }
 }
Пример #2
0
 /**
  * находит в указанном контексте (т.е. для набора пар поле - значение) объект с максимальным весом, меньшим чем у текущего, и меняет текущий объект с ним весами
  * т.е. объект поднимается на одну позицию вверх если сортировать по возрастанию веса
  * @param array $extra_fields_arr
  */
 public function swapWeights($extra_fields_arr = array())
 {
     $current_class_name = self::getMyClassName();
     $current_item_weight = $this->getWeight();
     $where_arr = array('weight < ?');
     $params_arr = array($current_item_weight);
     if (!empty($extra_fields_arr)) {
         foreach ($extra_fields_arr as $extra_field_name => $extra_field_value) {
             $extra_field_name = preg_replace('|[^a-zA-Z0-9_]|', '', $extra_field_name);
             if (is_null($extra_field_value)) {
                 $where_arr[] = $extra_field_name . ' is null';
             } else {
                 $where_arr[] = $extra_field_name . '=?';
                 $params_arr[] = $extra_field_value;
             }
         }
     }
     $sql = 'SELECT id FROM ' . self::DB_TABLE_NAME . ' WHERE ' . implode(' AND ', $where_arr) . ' ORDER BY weight DESC, id DESC LIMIT 1';
     $object_to_swap_weights_id = \OLOG\DB\DBWrapper::readField(self::DB_ID, $sql, $params_arr);
     if (!$object_to_swap_weights_id) {
         return;
     }
     $object_to_swap_weights_obj = $current_class_name::factory($object_to_swap_weights_id);
     $object_to_swap_weights_weight = $object_to_swap_weights_obj->getWeight();
     $this->setWeight($object_to_swap_weights_weight);
     $this->save();
     $object_to_swap_weights_obj->setWeight($current_item_weight);
     $object_to_swap_weights_obj->save();
 }
Пример #3
0
 public static function getIdsArrForVocabularyIdByCreatedAtDesc($value, $offset = 0, $page_size = 30)
 {
     if (is_null($value)) {
         return \OLOG\DB\DBWrapper::readColumn(self::DB_ID, 'select id from ' . self::DB_TABLE_NAME . ' where vocabulary_id is null order by created_at_ts desc limit ' . intval($page_size) . ' offset ' . intval($offset));
     } else {
         return \OLOG\DB\DBWrapper::readColumn(self::DB_ID, 'select id from ' . self::DB_TABLE_NAME . ' where vocabulary_id = ? order by created_at_ts desc limit ' . intval($page_size) . ' offset ' . intval($offset), array($value));
     }
 }
Пример #4
0
 public function testAfterDeleteAndTransaction()
 {
     \PHPModelDemo\ModelDemoConfig::init();
     // нормальное удаление модели
     $obj = new \Tests\TestModel();
     $obj->setThrowExceptionAfterDelete(true);
     $obj->save();
     $obj_id = $obj->getId();
     $this->expectException(\Exception::class);
     $this->expectExceptionMessage('After delete');
     $obj->delete();
     $test_model_ids_arr = \OLOG\DB\DBWrapper::readColumn(\Tests\TestModel::DB_ID, 'select id from ' . \Tests\TestModel::DB_TABLE_NAME . ' where id = ?', array($obj_id));
     $this->assertEquals(1, count($test_model_ids_arr));
     // проверяем что запись в БД осталась, т.е. транзакция с удалением была откачена
 }
Пример #5
0
 /**
  * Тест проверяет создание, сохранение, загрузку и удаление объекта через activeRecord и factory
  */
 public function testSaveLoadDelete()
 {
     \PHPModelDemo\ModelDemoConfig::init();
     $test_title = rand(1, 10000);
     $new_model = new \Tests\TestModel();
     $new_model->setTitle($test_title);
     $new_model->save();
     $test_model_id = $new_model->getId();
     $this->assertNotEmpty($test_model_id);
     // тестирует генерацию непустого идентификатора модели при первом сохранении
     $loaded_model_obj = \Tests\TestModel::factory($test_model_id);
     $this->assertEquals($test_title, $loaded_model_obj->getTitle());
     // тестируем совпадение заголовков сохраненной и загруженной модели
     $loaded_model_obj->delete();
     $test_model_ids_arr = \OLOG\DB\DBWrapper::readColumn(\Tests\TestModel::DB_ID, 'select id from ' . \Tests\TestModel::DB_TABLE_NAME . ' where id = ?', array($test_model_id));
     $this->assertEquals(0, count($test_model_ids_arr));
     // проверяем что записей с таким ИД в таблице нет
 }
Пример #6
0
 public static function getAllIdsArrByCreatedAtDesc()
 {
     $ids_arr = \OLOG\DB\DBWrapper::readColumn(self::DB_ID, 'select id from ' . self::DB_TABLE_NAME . ' order by created_at_ts desc');
     return $ids_arr;
 }
Пример #7
0
 public static function getAllIdsArrByCreatedAtDesc($offset = 0, $page_size = 30)
 {
     $ids_arr = \OLOG\DB\DBWrapper::readColumn(self::DB_ID, 'select id from ' . self::DB_TABLE_NAME . ' order by created_at_ts desc limit ' . intval($page_size) . ' offset ' . intval($offset));
     return $ids_arr;
 }
Пример #8
0
 public static function process_db($db_id)
 {
     // checking DB connectivity
     $db_obj = null;
     try {
         $db_obj = \OLOG\DB\DBFactory::getDB($db_id);
     } catch (\Exception $e) {
         echo $e->getMessage() . "\n\n";
     }
     if (!$db_obj) {
         echo CliUtil::delimiter();
         echo "Can't connect to database " . $db_id . "\n";
         echo "Probable problems:\n";
         echo "- misconfiguration. App config for database:\n";
         //echo var_export(DBFactory::getConfigArr($db_id)) . "\n"; // TODO: fix
         echo "- database server not accessible\n";
         echo "- database not created. It must be created manually.\n";
         exit;
     }
     $executed_queries_sql_arr = [];
     try {
         $executed_queries_sql_arr = \OLOG\DB\DBWrapper::readColumn($db_id, 'select sql_query from ' . self::EXECUTED_QUERIES_TABLE_NAME);
     } catch (\Exception $e) {
         echo CliUtil::delimiter();
         echo "Can not load the executed queries list from " . self::EXECUTED_QUERIES_TABLE_NAME . " table:\n";
         echo $e->getMessage() . "\n\n";
         echo "Probably the " . self::EXECUTED_QUERIES_TABLE_NAME . " table was not created. Choose:\n";
         echo "\tENTER to create table and proceed\n";
         // TODO: constants
         echo "\tany other key to exit\n";
         $command_str = CliUtil::readStdinAnswer();
         // TODO: switch
         if ($command_str == '') {
             // TODO: constants
             \OLOG\DB\DBWrapper::query($db_id, 'create table ' . self::EXECUTED_QUERIES_TABLE_NAME . ' (id int not null auto_increment primary key, created_at_ts int not null, sql_query text) engine InnoDB default charset utf8');
         } else {
             exit;
         }
     }
     $sql_arr = self::loadSqlArrForDB($db_id);
     foreach ($sql_arr as $sql) {
         if (!in_array($sql, $executed_queries_sql_arr)) {
             echo CliUtil::delimiter();
             echo $sql . "\n";
             // TODO: constants
             echo "\n";
             echo "\t" . self::COMMAND_SKIP_QUERY . ": skip query now, do not mark as executed\n";
             echo "\t" . self::COMMAND_IGNORE_QUERY . ": ignore query - mark as executed, but do not execute (you can execute one manually)\n";
             echo "\tENTER execute query\n";
             $command_str = CliUtil::readStdinAnswer();
             switch ($command_str) {
                 case '':
                     \OLOG\DB\DBWrapper::query($db_id, $sql);
                     \OLOG\DB\DBWrapper::query($db_id, 'insert into ' . self::EXECUTED_QUERIES_TABLE_NAME . ' (created_at_ts, sql_query) values (?, ?)', array(time(), $sql));
                     echo "Query executed.\n";
                     break;
                 case self::COMMAND_IGNORE_QUERY:
                     \OLOG\DB\DBWrapper::query($db_id, 'insert into ' . self::EXECUTED_QUERIES_TABLE_NAME . ' (created_at_ts, sql_query) values (?, ?)', array(time(), $sql));
                     echo "Query marked as executed without execution.\n";
                     break;
                 case self::COMMAND_SKIP_QUERY:
                     echo "Query skipped.\n";
                     break;
                 default:
                     //echo "Unknown command.\n";
                     throw new \Exception('unknown command');
                     break;
                     // TODO: repeat entry?
             }
         }
     }
 }
 /**
  * Возвращает одну страницу списка объектов указанного класса.
  * Сортировка: TODO.
  * Фильтры: массив $context_arr.
  * Как определяется страница: см. Pager.
  * @param $model_class_name Имя класса модели
  * @param $context_arr array Массив пар "имя поля" - "значение поля"
  * @return array Массив идентикаторов объектов.
  */
 public static function getObjIdsArrForClassName($table_index_on_page, $model_class_name, $filters_arr, $order_by = '')
 {
     \OLOG\CheckClassInterfaces::exceptionIfClassNotImplementsInterface($model_class_name, \OLOG\Model\InterfaceLoad::class);
     $page_size = Pager::getPageSize($table_index_on_page);
     $start = Pager::getPageOffset($table_index_on_page);
     $db_table_name = $model_class_name::DB_TABLE_NAME;
     $db_id = $model_class_name::DB_ID;
     $db_id_field_name = CRUDFieldsAccess::getIdFieldName($model_class_name);
     $query_param_values_arr = array();
     $where = ' 1 = 1 ';
     foreach ($filters_arr as $filter_obj) {
         /*
         if ($filter_obj instanceof InterfaceCRUDTableFilter) {
         
             $column_name = $filter_obj->getFieldName();
             $operation_code = $filter_obj->getOperationCode();
             $value = $filter_obj->getValue();
         
             $column_name = preg_replace("/[^a-zA-Z0-9_]+/", "", $column_name);
         
             switch ($operation_code) {
                 case CRUDTableFilter::FILTER_EQUAL:
                     $where .= ' and ' . $column_name . ' = ? ';
                     $query_param_values_arr[] = $value;
                     break;
         
                 case CRUDTableFilter::FILTER_IS_NULL:
                     $where .= ' and ' . $column_name . ' is null ';
                     break;
         
                 case CRUDTableFilter::FILTER_LIKE:
                     $where .= ' and ' . $column_name . ' like ? ';
                     $query_param_values_arr[] = '%' . $value . '%';
                     break;
         
                 case CRUDTableFilter::FILTER_IN:
                     if (count($value)) {
                         $in_placeholders_arr = [];
         
                         foreach ($value as $in_single_value) {
                             $in_placeholders_arr[] = '?';
                             $query_param_values_arr[] = $in_single_value;
                         }
         
                         $where .= ' and ' . $column_name . ' in (' . implode(', ', $in_placeholders_arr) . ') ';
                     }
                     break;
         
                 default:
                     throw new \Exception('unknown filter code');
             }
         } else
         */
         if ($filter_obj instanceof InterfaceCRUDTableFilter2) {
             list($filter_sql_condition, $filter_placeholder_values_arr) = $filter_obj->sqlConditionAndPlaceholderValue();
             if ($filter_sql_condition != '') {
                 $where .= ' and ' . $filter_sql_condition;
             }
             $query_param_values_arr = array_merge($query_param_values_arr, $filter_placeholder_values_arr);
         } elseif ($filter_obj instanceof InterfaceCRUDTableFilterInvisible) {
             list($filter_sql_condition, $filter_placeholder_values_arr) = $filter_obj->sqlConditionAndPlaceholderValue();
             if ($filter_sql_condition != '') {
                 $where .= ' and ' . $filter_sql_condition;
             }
             $query_param_values_arr = array_merge($query_param_values_arr, $filter_placeholder_values_arr);
         } else {
             throw new \Exception('filter doesnt implement InterfaceCRUDTableFilter nor InterfaceCRUDTableFilter2');
         }
     }
     if ($order_by == '') {
         $order_by = $db_id_field_name;
     }
     $obj_ids_arr = \OLOG\DB\DBWrapper::readColumn($db_id, "select " . $db_id_field_name . " from " . $db_table_name . ' where ' . $where . ' order by ' . $order_by . ' limit ' . intval($page_size) . ' offset ' . intval($start), $query_param_values_arr);
     return $obj_ids_arr;
 }
Пример #10
0
 /**
  * @param $login
  * @param $password_from_form
  * @return null
  */
 public static function getUserIdByCredentials($login, $password_from_form)
 {
     $data = \OLOG\DB\DBWrapper::readObject(\OLOG\Auth\AuthConstants::DB_NAME_PHPAUTH, 'SELECT id, password_hash FROM ' . User::DB_TABLE_NAME . ' WHERE login = ?', array($login));
     if ($data === false) {
         return null;
     }
     $password_check_result = password_verify($password_from_form, $data->password_hash);
     if (!$password_check_result) {
         return null;
     }
     return $data->id;
 }
Пример #11
0
 public static function getPermissionIdsArrForUserId($value)
 {
     return \OLOG\DB\DBWrapper::readColumn(self::DB_ID, 'select permission_id from ' . self::DB_TABLE_NAME . ' where user_id = ?', array($value));
 }
Пример #12
0
    public function html($obj)
    {
        $field_name = $this->getFieldName();
        $referenced_class_name = $this->getReferencedClassName();
        $referenced_class_title_field = $this->getReferencedClassTitleField();
        $field_value = CRUDFieldsAccess::getObjectFieldValue($obj, $field_name);
        $options_html_arr = ['<option value=""></option>'];
        // TODO: check referenced class interfaces
        $referenced_obj_ids_arr = \OLOG\DB\DBWrapper::readColumn($referenced_class_name::DB_ID, 'select ID from ' . $referenced_class_name::DB_TABLE_NAME . ' order by ID');
        $options_arr = [];
        foreach ($referenced_obj_ids_arr as $id) {
            $obj = CRUDObjectLoader::createAndLoadObject($referenced_class_name, $id);
            $options_arr[$id] = CRUDFieldsAccess::getObjectFieldValue($obj, $referenced_class_title_field);
        }
        foreach ($options_arr as $value => $title) {
            $selected_html_attr = '';
            if ($field_value == $value) {
                $selected_html_attr = ' selected';
            }
            $options_html_arr[] = '<option value="' . $value . '"' . $selected_html_attr . '>' . $title . '</option>';
            // TODO: sanitize
        }
        $html = '';
        $select_element_id = 'js_select_' . rand(1, 999999);
        $html .= '<select id="' . Sanitize::sanitizeAttrValue($select_element_id) . '" name="' . Sanitize::sanitizeAttrValue($field_name) . '" class="form-control">' . implode('', $options_html_arr) . '</select>';
        $html .= '<input type="hidden" id="' . Sanitize::sanitizeAttrValue($select_element_id) . '_is_null" name="' . Sanitize::sanitizeAttrValue($field_name) . '___is_null"/>';
        ob_start();
        ?>
        <script>
            var select_element = document.getElementById('<?php 
        echo $select_element_id;
        ?>
');
            select_element.addEventListener(
                'change',
                function(){
                    var select_element_id = document.getElementById('<?php 
        echo $select_element_id;
        ?>
');
                    var is_null_element = document.getElementById('<?php 
        echo $select_element_id;
        ?>
_is_null');
                    var value = select_element_id.options[select_element_id.selectedIndex].value;

                    if (value == ''){
                        is_null_element.value = '1';
                    } else {
                        is_null_element.value = '';
                    }
                }
            );

            select_element.dispatchEvent(new Event('change')); // fire to initialize is_null input on display
        </script>

        <?php 
        $html .= ob_get_clean();
        return $html;
    }
Пример #13
0
 /**
  * Удаление записи
  * @param $model_obj
  * @return \PDOStatement
  */
 public static function deleteModelObj($model_obj)
 {
     self::exceptionIfObjectIsIncompatibleWithActiveRecord($model_obj);
     $model_class_name = get_class($model_obj);
     $db_id = $model_class_name::DB_ID;
     $db_table_name = $model_class_name::DB_TABLE_NAME;
     $db_id_field_name = self::getIdFieldName($model_obj);
     $reflect = new \ReflectionClass($model_obj);
     $property_obj = $reflect->getProperty($db_id_field_name);
     $property_obj->setAccessible(true);
     $model_id_value = $property_obj->getValue($model_obj);
     if ($model_id_value == '') {
         throw new \Exception('Deleting not saved object');
     }
     $result = \OLOG\DB\DBWrapper::query($db_id, 'DELETE FROM ' . $db_table_name . ' where ' . $db_id_field_name . ' = ?', array($model_id_value));
     //\OLOG\Logger\Logger::logObjectEvent($model_obj, 'DELETE');
     return $result;
 }
Пример #14
0
<?php

require_once '../vendor/autoload.php';
\PHPModelDemo\ModelDemoConfig::init();
echo '<div>MODELS <a href="/?a=add_model">+</a></div>';
// ACTIONS
if (isset($_GET['a'])) {
    if ($_GET['a'] == 'add_model') {
        $new_model = new \PHPModelDemo\DemoModel();
        $new_model->setTitle(rand(1, 1000));
        $new_model->save();
    }
}
// DISPLAY
$models_ids_arr = \OLOG\DB\DBWrapper::readColumn(\PHPModelDemo\ModelDemoConfig::DB_NAME_PHPMODELDEMO, 'select id from ' . \PHPModelDemo\DemoModel::DB_TABLE_NAME . ' order by id desc');
echo '<ul>';
foreach ($models_ids_arr as $model_id) {
    $model_obj = \PHPModelDemo\DemoModel::factory($model_id);
    echo '<div>' . $model_obj->getTitle() . '</div>';
}
echo '</ul>';
echo '<div>CONST MODELS <a href="/?a=add_constmodel">+</a></div>';
// ACTIONS
if (isset($_GET['a'])) {
    if ($_GET['a'] == 'add_constmodel') {
        $new_model = new \PHPModelDemo\ConstTest();
        $new_model->setTitle(rand(1, 1000));
        $new_model->save();
    }
}
// DISPLAY