/** * компиляция строки: разворачивание обращений к полям объектов * @param $str * @param array $data * @return mixed * @throws \Exception */ public static function compile($str, array $data) { // TODO: clean and finish $matches = []; // сначала подставляем значения в самых внутренних фигурных скобках, потом которые снаружи, и так пока все скобки не будут заменены // поддерживается два вида выражений: // - {obj->field} заменяется на значение поля field объекта obj. obj - это ключ массива data, т.е. здесь можно использовать такие строки, которые передаются сюда вызывающими функциями // -- обычно виджеты передают объект, который показывается в виджете, с именем this // - {class_name.id->field} заменяется на значение поля field объекта класса class_name с идентификатором id while (preg_match('@{([^}{]+)}@', $str, $matches)) { $expression = $matches[1]; $replacement = 'UNKNOWN_EXPRESSION'; $magic_matches = []; if (preg_match('@^(\\w+)\\->([\\w()]+)$@', $expression, $magic_matches)) { $obj_key_in_data = $magic_matches[1]; $obj_field_name = $magic_matches[2]; $obj = $data[$obj_key_in_data]; $replacement = self::getReplacement($obj, $obj_field_name); } if (preg_match('@^([\\w\\\\]+)\\.(\\w+)->([\\w()]+)$@', $expression, $magic_matches)) { $class_name = $magic_matches[1]; $obj_id = $magic_matches[2]; $obj_field_name = $magic_matches[3]; if ($obj_id != self::NULL_STRING) { // TODO: review? $obj = CRUDObjectLoader::createAndLoadObject($class_name, $obj_id); $replacement = self::getReplacement($obj, $obj_field_name); } else { $replacement = ''; // пустая строка для случаев типа '{' . Sport::class . '.{this->sport_id}->title}' и this->sport_id не установленно } } // здесь заменяем только первое вхождение, потому что выше мы обрабатывали только первое вхождение // если не сделать это ограничение - вот такое выражение // new \OLOG\CRUD\CRUDTableWidgetText('{this->video_width}x{this->video_height}')) // выдаст "video_width Х video_width" // т.е. для прочитает первые скобки, а потом два заменит на результат и первые, и вторые $str = preg_replace('@{([^}{]+)}@', $replacement, $str, 1); } if (self::NULL_STRING == $str) { return null; } return $str; }
protected static function saveEditorFormOperation($url_to_redirect_after_save = '', $redirect_get_params_arr = []) { $model_class_name = POSTAccess::getRequiredPostValue(self::FIELD_CLASS_NAME); $object_id = self::saveOrUpdateObjectFromFormData(); if ($url_to_redirect_after_save != '') { $obj = CRUDObjectLoader::createAndLoadObject($model_class_name, $object_id); $redirect_url = $url_to_redirect_after_save; $redirect_url = CRUDCompiler::compile($redirect_url, ['this' => $obj]); $params_arr = []; foreach ($redirect_get_params_arr as $param => $value) { $params_arr[$param] = CRUDCompiler::compile($value, ['this' => $obj]); } if (!empty($redirect_get_params_arr)) { $redirect_url = $url_to_redirect_after_save . '?' . http_build_query($params_arr); } \OLOG\Redirects::redirect($redirect_url); } // keep get form \OLOG\Redirects::redirectToSelf(); }
public static function html($model_class_name, $create_form_html, $column_obj_arr, $parent_id_field_name, $order_by = '', $table_id = '1', $filters_arr = [], $col_with_padding_index = 0, $filters_position = CRUDTable::FILTERS_POSITION_NONE) { // TODO: придумать способ автогенерации table_id, который был бы уникальным, но при этом один и тот же когда одну таблицу запрашиваешь несколько раз CRUDTable::executeOperations(); $objs_ids_arr = CRUDInternalTableObjectsSelector::getRecursiveObjIdsArrForClassName($model_class_name, $parent_id_field_name, $filters_arr, $order_by); // // вывод таблицы // $table_container_element_id = 'tableContainer_' . $table_id; // оборачиваем в отдельный div для выдачи только таблицы аяксом - иначе корневой элемент документа не будет доступен в jquery селекторах $html = '<div>'; $html .= '<div class="' . $table_container_element_id . ' row">'; if ($filters_position == CRUDTable::FILTERS_POSITION_LEFT) { $html .= '<div class="col-sm-4">'; $html .= self::filtersHtml($filters_arr); $html .= '</div>'; $html .= '<div class="col-sm-8">'; } else { $html .= '<div class="col-sm-12">'; } $html .= self::toolbarHtml($table_id, $create_form_html); if ($filters_position == CRUDTable::FILTERS_POSITION_TOP) { $html .= self::filtersHtml($filters_arr); } $html .= '<table class="table table-hover">'; $html .= '<thead>'; $html .= '<tr>'; /** @var InterfaceCRUDTableColumn $column_obj */ foreach ($column_obj_arr as $column_obj) { Assert::assert($column_obj instanceof InterfaceCRUDTableColumn); $html .= '<th>' . Sanitize::sanitizeTagContent($column_obj->getTitle()) . '</th>'; } $html .= '</tr>'; $html .= '</thead>'; $html .= '<tbody>'; foreach ($objs_ids_arr as $obj_data) { $obj_id = $obj_data['id']; $obj_obj = CRUDObjectLoader::createAndLoadObject($model_class_name, $obj_id); $html .= '<tr>'; /** @var InterfaceCRUDTableColumn $column_obj */ foreach ($column_obj_arr as $col_index => $column_obj) { Assert::assert($column_obj instanceof InterfaceCRUDTableColumn); /** @var InterfaceCRUDTableWidget $widget_obj */ $widget_obj = $column_obj->getWidgetObj(); Assert::assert($widget_obj); Assert::assert($widget_obj instanceof InterfaceCRUDTableWidget); $col_width_attr = ''; if ($widget_obj instanceof CRUDTableWidgetDelete) { $col_width_attr = ' width="1px" '; } if ($widget_obj instanceof CRUDTableWidgetWeight) { $col_width_attr = ' width="1px" '; } $html .= '<td ' . $col_width_attr . '>'; if ($col_index == $col_with_padding_index) { $html .= '<div style="padding-left: ' . $obj_data['depth'] * 30 . 'px;">'; } $html .= $widget_obj->html($obj_obj); if ($col_index == 0) { $html .= '</div>'; } $html .= '</td>'; } $html .= '</tr>'; } $html .= '</tbody>'; $html .= '</table>'; $html .= '</div>'; $html .= '</div>'; $html .= '</div>'; // Загрузка скриптов $html .= CRUDTableScript::getHtml($table_container_element_id, Url::getCurrentUrlNoGetForm()); return $html; }
/** * table_id - это идентификатор таблицы на странице, к которому привязываются все данные: имена полей формы и т.п. * @param $model_class_name * @param $create_form_html * @param $column_obj_arr * @param array $filters_arr * @param string $order_by * @return string */ public static function html($model_class_name, $create_form_html, $column_obj_arr, $filters_arr = [], $order_by = '', $table_id = '', $filters_position = self::FILTERS_POSITION_NONE) { // TODO: придумать способ автогенерации table_id, который был бы уникальным, но при этом один и тот же когда одну таблицу запрашиваешь несколько раз self::executeOperations(); // // вывод таблицы // $table_container_element_id = uniqid('tableContainer_'); if ($table_id) { $table_container_element_id = $table_id; } // оборачиваем в отдельный div для выдачи только таблицы аяксом - иначе корневой элемент документа не будет доступен в jquery селекторах $html = HTML::div($table_container_element_id, '', function () use($model_class_name, $create_form_html, $column_obj_arr, $filters_arr, $order_by, $table_id, $filters_position) { echo '<div class="row">'; if ($filters_position == self::FILTERS_POSITION_LEFT) { echo '<div class="col-sm-4">'; echo self::filtersHtml($table_id, $filters_arr); echo '</div>'; } $col_sm_class = '12'; if ($filters_position == self::FILTERS_POSITION_LEFT || $filters_position == self::FILTERS_POSITION_RIGHT) { $col_sm_class = '8'; } echo '<div class="col-sm-' . $col_sm_class . '">'; echo self::toolbarHtml($table_id, $create_form_html, $filters_arr); if ($filters_position == self::FILTERS_POSITION_TOP) { echo self::filtersHtml($table_id, $filters_arr); } if ($filters_position == self::FILTERS_POSITION_INLINE) { echo self::filtersHtmlInline($table_id, $filters_arr); } echo '<table class="table table-hover">'; /** @var InterfaceCRUDTableColumn $column_obj */ echo '<thead><tr>'; foreach ($column_obj_arr as $column_obj) { Assert::assert($column_obj instanceof InterfaceCRUDTableColumn); echo '<th>' . Sanitize::sanitizeTagContent($column_obj->getTitle()) . '</th>'; } echo '</tr></thead>'; echo '<tbody>'; $objs_ids_arr = CRUDInternalTableObjectsSelector::getObjIdsArrForClassName($table_id, $model_class_name, $filters_arr, $order_by); foreach ($objs_ids_arr as $obj_id) { $obj_obj = CRUDObjectLoader::createAndLoadObject($model_class_name, $obj_id); /** @var InterfaceCRUDTableColumn $column_obj */ echo '<tr>'; foreach ($column_obj_arr as $column_obj) { Assert::assert($column_obj instanceof InterfaceCRUDTableColumn); /** @var InterfaceCRUDTableWidget $widget_obj */ $widget_obj = $column_obj->getWidgetObj(); Assert::assert($widget_obj); Assert::assert($widget_obj instanceof InterfaceCRUDTableWidget); $col_width_attr = ''; if ($widget_obj instanceof CRUDTableWidgetDelete) { $col_width_attr = ' width="1px" '; } if ($widget_obj instanceof CRUDTableWidgetWeight) { $col_width_attr = ' width="1px" '; } echo '<td ' . $col_width_attr . ' style="word-break: break-all;">'; echo $widget_obj->html($obj_obj); echo '</td>'; } echo '</tr>'; } echo '</tbody>'; echo '</table>'; echo Pager::renderPager($table_id, count($objs_ids_arr)); echo '</div>'; if ($filters_position == self::FILTERS_POSITION_RIGHT) { echo '<div class="col-sm-4">'; echo self::filtersHtml($table_id, $filters_arr); echo '</div>'; } echo '</div>'; }); // Загрузка скриптов $html .= CRUDTableScript::getHtml($table_container_element_id, Url::getCurrentUrlNoGetForm()); return $html; }
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; }
public function htmlForValue($field_value, $input_name = null) { $field_name = $this->getFieldName(); if (is_null($input_name)) { $input_name = $field_name; } $referenced_class_name = $this->getReferencedClassName(); $referenced_class_title_field = $this->getReferencedClassTitleField(); $referenced_obj_title = ''; $disabled_btn_link = 'disabled'; $is_null_value = ''; if (is_null($field_value)) { $is_null_value = "1"; } if (!is_null($field_value)) { $referenced_obj = CRUDObjectLoader::createAndLoadObject($referenced_class_name, $field_value); $referenced_obj_title = CRUDFieldsAccess::getObjectFieldValue($referenced_obj, $referenced_class_title_field); $disabled_btn_link = ''; } $is_required_str = ''; if ($this->is_required) { $is_required_str = ' required '; } $html = ''; $html .= Preloader::preloaderJsHtml(); $select_element_id = 'js_select_' . rand(1, 999999); $choose_form_element_id = 'collapse_' . rand(1, 999999); $html .= '<input type="hidden" id="' . Sanitize::sanitizeAttrValue($select_element_id) . '" name="' . Sanitize::sanitizeAttrValue($input_name) . '" value="' . $field_value . '" data-field="' . Sanitize::sanitizeAttrValue($select_element_id) . '_text" ' . $is_required_str . '/>'; $html .= '<input type="hidden" id="' . Sanitize::sanitizeAttrValue($select_element_id) . '_is_null" name="' . Sanitize::sanitizeAttrValue($input_name) . '___is_null" value="' . $is_null_value . '"/>'; $html .= '<div class="input-group">'; if ($this->getAjaxActionUrl()) { $html .= '<span class="input-group-btn">'; $html .= '<button type="button" class="btn btn-default" data-toggle="modal" data-target="#' . $choose_form_element_id . '"><span class="glyphicon glyphicon-folder-open"></span></button>'; $html .= '<button type="button" id="' . Sanitize::sanitizeAttrValue($select_element_id) . '_btn_is_null" class="btn btn-default"><span class="glyphicon glyphicon-remove"></span></button>'; $html .= '</span>'; } $html .= '<div class="form-control" id="' . Sanitize::sanitizeAttrValue($select_element_id) . '_text">' . $referenced_obj_title . '</div>'; if ($this->getEditorUrl()) { $html .= '<span class="input-group-btn">'; $html .= '<button ' . $disabled_btn_link . ' type="button" id="' . Sanitize::sanitizeAttrValue($select_element_id) . '_btn_link" class="btn btn-default">Перейти</button>'; $html .= '</span>'; } $html .= '</div>'; $html .= BT::modal($choose_form_element_id, 'Выбрать'); ob_start(); ?> <script> $('#<?php echo $choose_form_element_id; ?> ').on('hidden.bs.modal', function () { $('#<?php echo $choose_form_element_id; ?> .modal-body').html(''); }); $('#<?php echo $choose_form_element_id; ?> ').on('shown.bs.modal', function (e) { OLOG.preloader.show(); $.ajax({ url: "<?php echo $this->getAjaxActionUrl(); ?> " }).success(function(received_html) { $('#<?php echo $choose_form_element_id; ?> .modal-body').html(received_html); OLOG.preloader.hide(); }); }); $('#<?php echo $choose_form_element_id; ?> ').on('click', '.js-ajax-form-select', function (e) { e.preventDefault(); var select_id = $(this).data('id'); var select_title = $(this).data('title'); $('#<?php echo $choose_form_element_id; ?> ').modal('hide'); $('#<?php echo $select_element_id; ?> _text').text(select_title); $('#<?php echo $select_element_id; ?> _btn_link').attr('disabled', false); $('#<?php echo $select_element_id; ?> ').val(select_id).trigger('change'); $('#<?php echo $select_element_id; ?> _is_null').val(''); }); $('#<?php echo $select_element_id; ?> _btn_is_null').on('click', function (e) { e.preventDefault(); $('#<?php echo $select_element_id; ?> _text').text(''); $('#<?php echo $select_element_id; ?> _btn_link').attr('disabled', true); $('#<?php echo $select_element_id; ?> ').val('').trigger('change'); $('#<?php echo $select_element_id; ?> _is_null').val(1); }); $('#<?php echo $select_element_id; ?> _btn_link').on('click', function (e) { var url = '<?php echo $this->getEditorUrl(); ?> '; var id = $('#<?php echo $select_element_id; ?> ').val(); url = url.replace('REFERENCED_ID', id); window.location = url; }); </script> <?php $html .= ob_get_clean(); return $html; }