Поле, с помощью которого админ сможет менять автора записи ТК прямо из списка записей или из самой записи. Кроме поля напишем еще небольшой компонент, в котором будут храниться экшены для обработки аякс-запросов. Здесь не будет поиска пользователей по никнейму или почте. Для смены автора нужно знать и ввести id нового автора.
Начнем с поля.
Как и другие поля, наше поле будет состоять из двух обязательных файлов, а также из файла стилей и файла скриптов. Создадим их.
- system/fields/changeuserid.php
- templates/default/assets/fields/changeuserid.tpl.php
- templates/default/css/fields/changeuserid.css
- templates/default/js/fields/changeuserid.js
Если вы вдруг обнаружили, что у вас нет папки fields в папках css и js, то создайте.
Файл templates/default/assets/fields/changeuserid.tpl.php будет пустым, создали и закройте.
В файл system/fields/changeuserid.php добавим такой код (описание в комментариях прямо в коде):
<?php class fieldChangeuserid extends cmsFormField{ public $title = 'Смена user_id записи'; public $sql = ''; public $is_virtual = true; public $allow_index = false; public function parse($value) { // если пользователь не админ - поле не выводим if (!cmsUser::get('is_admin')) { return ''; } $id = $this->item['id']; // id записи $user = cmsCore::getModel('users')->getUser($this->item['user_id']); // ищем автора записи среди всех пользователей // по-умолчанию будем считать, что пользователя нет // например, если вы его случайно удалили каким-то образом, не через админку $avatar = ''; // нет аватара $nickname = 'Пользователь удален'; // нет никнейма $not_avatar = ' not_avatar'; // это класс для кнопки // если пользователь есть if ($user) { // получаем аватар // выводим загруженный аватар, заглушку или буквенный аватар $avatar = $user['avatar'] || !function_exists('html_avatar_image_empty') ? html_avatar_image($user['avatar'], 'micro', $user['nickname']) : html_avatar_image_empty($user['nickname'], 'avatar__mini'); $nickname = $user['nickname']; // никнейм $not_avatar = ''; // удаляем класс not_avatar } // подключаем к шаблону файлы стилей и скриптов cmsTemplate::getInstance()->addCSS('templates/default/css/fields/changeuserid.css'); cmsTemplate::getInstance()->addJS('templates/default/js/fields/changeuserid.js'); // кнопка для начала смены автора // вешаем на нее событие onclick, вызывающее js-функцию changeuserid_start, // в которую мы передадим id записи, id текущего автора и имя типа контента $change_btn = '<div class="changeuserid_btn changeuserid_btn_'.$id.'" onclick="changeuserid_start('.$id.', '.$this->item['user_id'].', \''.$this->item['ctype_name'].'\')">↺</div>'; // выводим результат // это блок с классом changeuserid_user_123 (123 - это id записи) // внутри ссылка на пользователя с аватаром и никнеймом return '<div class="changeuserid_user'.$not_avatar.' changeuserid_user_'.$id.'"><a href="'.href_to('users', $this->item['user_id']).'" target="_blank">'.$avatar.$nickname.'</a>'.$change_btn.'</div>'; } }
Сразу добавим стили, чтобы больше к ним не возвращать. Думаю, пояснять css смысла нет. В файл templates/default/css/fields/changeuserid.css пишем код, сохраняем и закрываем:
.changeuserid_user a{ display:inline-block; vertical-align:top; border-radius:3px; background:#eee; color:#333; text-decoration:none!important; position:relative; padding:0 10px 0 42px; line-height:32px; overflow:hidden; transition:allease .15s; } .changeuserid_user.not_avatar a{ padding:0 10px; } .changeuserid_user a:hover{ background:#ddd; color:#000; } .changeuserid_user .icms-profile-avatar__default, .changeuserid_user img{ position:absolute; top:0; left:0; } .changeuserid_btn{ display:inline-block; vertical-align:top; width:32px; height:32px; text-align:center; line-height:32px; border-radius:3px; background:#888; color:#f5f5f5; font-size:18px; transition:all ease .15s; margin-left:5px; cursor:pointer; opacity:.8; } .changeuserid_btn_yes{ background:#a6d38f; font-size:16px; } .changeuserid_btn_no{ background:#f16868; font-size:16px; } .changeuserid_btn:hover{ opacity:1; } .changeuserid_input{ height:32px; width:80px; padding:0 10px; display:inline-block; }
В файле system/fields/changeuserid.php, если присмотреться, у нас есть js-событие onclick, вызывающее функцию changeuserid_start. Добавим ее в файл templates/default/js/fields/changeuserid.js
function changeuserid_start(id, user_id, ctype_name){ /* удаляем кнопку */ $('.changeuserid_btn_' + id).remove(); /* отправляем запрос экшену start с id записи, юзера и именем типа контента */ $.post('/changeuserid/start/' + id + '/' + user_id + '/' + ctype_name).done(function(response) { result = $.parseJSON(response); /* если вернулась ошибка, то перезагрузка страницы */ if (result.action === 'error') { window.location.reload(); } else { /* если нормально всё, то вместо ссылки на текущего автора покажем форму */ $('.changeuserid_user_' + id).html(result.form); } }); }
Здесь мы обращаемся к экшену start компонента changeuserid. Но у нас его еще нет. Поэтому создаем папку system/controllers/changeuserid, в ней файл frontend.php с таким содержимым:
<?php class changeuserid extends cmsFrontend {}
Сохраняем и закрываем. Теперь в этой же папке создаем папку actions, а в ней файл start.php:
<?php class actionChangeuseridStart extends cmsAction{ // сюда мы передали id записи, id текущего автора и имя типа контента public function run($id, $user_id, $ctype_name){ // возвращать будем массив $result с данными // по-умолчанию, пока не будут пройдены проверки, // мы возвращаем ошибку $result['action'] = 'error'; // убираем из имени типа контента всё лишнее, мало ли кто это балуется // если кнопки нажимает не админ или если id записи и автора не числа, то возвращаем ошибку return $this->cms_template->renderJSON($result); } // меняем $result['action'] на ok $result['action'] = 'ok'; // сформируем форму для ввода нового id пользователя // с кнопками подтверждения и отмены // кнопка подтверждения, вешаем на нее событие onclick, вызывающее js-функцию changeuserid_change, // в которую передадим id записи и имя ТК $btn_yes = '<div class="changeuserid_btn changeuserid_btn_yes" onclick="changeuserid_change('.$id.', \''.$ctype_name.'\')">✔</div>'; // кнопка отмены, вешаем на нее событие onclick, вызывающее js-функцию changeuserid_cancel, // в которую передадим id записи $btn_no = '<div class="changeuserid_btn changeuserid_btn_no" onclick="changeuserid_cancel('.$id.')">✖</div>'; // поле типа "число" $input = html_input('number', 'changeuserid', $user_id, ['class' => 'changeuserid_input changeuserid_input_'.$id]); // вся наша форма, состоит из поля и двух кнопок $result['form'] = $input.$btn_yes.$btn_no; // возвращаемся назад с нашей формой return $this->cms_template->renderJSON($result); } }
Здесь, как видно, еще две js-функции — changeuserid_change и changeuserid_cancel. Добавим их в наш js-файл:
function changeuserid_start(id, user_id, ctype_name){ /* удаляем кнопку */ $('.changeuserid_btn_' + id).remove(); /* отправляем запрос экшену start с id записи, юзера и именем типа контента */ $.post('/changeuserid/start/' + id + '/' + user_id + '/' + ctype_name).done(function(response) { result = $.parseJSON(response); /* если вернулась ошибка, то перезагрузка страницы */ if (result.action === 'error') { window.location.reload(); } else { /* если нормально всё, то вместо ссылки на текущего автора покажем форму */ $('.changeuserid_user_' + id).html(result.form); } }); } function changeuserid_change(id, ctype_name){ /* скрываем кнопки */ $('.changeuserid_user_' + id + ' .changeuserid_btn').hide(); /* получаем id нового автора из поля */ var user_id = $('.changeuserid_input_' + id).val(); /* отправляем запрос экшену change с id записи, юзера и именем типа контента */ $.post('/changeuserid/change/' + id + '/' + user_id + '/' + ctype_name).done(function(response) { result = $.parseJSON(response); /* если ошибка, то перезагружаем страницу */ if (result.action === 'error') { window.location.reload(); } /* если пользователь не найден */ if (result.action === 'user_not_found') { /* показываем сообщение */ alert(result.mess); /* возвращаем кнопки */ $('.changeuserid_user_' + id + ' .changeuserid_btn').show(); } /* если всё хорошо, то обновляем поле в этой записи */ if (result.action === 'ok'){ changeuseridUpd('.changeuserid_user_' + id); } }); } function changeuserid_cancel(id) { /* обновляем поле в этой записи */ changeuseridUpd('.changeuserid_user_' + id); } async function changeuseridUpd(elem) { try{ var html = await(await fetch(location.href)).text(); var newdoc = new DOMParser().parseFromString(html, 'text/html'); document.querySelector(elem).outerHTML = newdoc.querySelector(elem).outerHTML; } catch (err) { $(elem).remove(); } return true; }
Здесь же добавили еще одну функцию — changeuseridUpd. Эта функция для обновления элемента на странице.
Как видно в коде, если админ введет id нового автора и нажмет на кнопку с подтверждения, то мы обратимся еще к одному экшену — change. Поэтому добавим еще один файл в папке system/controllers/changeuserid/actions — change.php с таким кодом:
<?php class actionChangeuseridChange extends cmsAction{ // сюда мы передали id записи, id нового автора и имя типа контента public function run($id, $user_id, $ctype_name){ // возвращать будем массив $result с данными // по-умолчанию, пока не будут пройдены проверки, // мы возвращаем ошибку $result['action'] = 'error'; // если кнопки нажимает не админ или если id записи и автора не числа, то возвращаем ошибку return $this->cms_template->renderJSON($result); } // убираем из имени типа контента всё лишнее, мало ли кто это балуется // получаем модель контента $content_model = cmsCore::getModel('content'); // ищем тип контента по имени $ctype = $content_model->getContentTypeByName($ctype_name); // если не находим, то возвращаем ошибку if (!$ctype) { return $this->cms_template->renderJSON($result); } // ищем пользователя с помощью модели пользователей $user = cmsCore::getModel('users')->getUser($user_id); // если нет пользователя с таким id, то формируем сообщение об ошибке и возвращаемся if (!$user) { $result['action'] = 'user_not_found'; $result['mess'] = 'Пользователь не найден!'; return $this->cms_template->renderJSON($result); } // если всё нормально, то обновляем пользователя у записи $content_model->update('con_'.$ctype_name, $id, ['user_id' => $user_id]); $result['action'] = 'ok'; // и возвращаемся return $this->cms_template->renderJSON($result); } }
Вот и всё. Чтобы использовать на сайте, добавьте поле в типе контента.
Еще раз, какие должны быть файлы:
- system/controllers/changeuserid/frontend.php
- system/controllers/changeuserid/actions/start.php
- system/controllers/changeuserid/actions/change.php
- system/fields/changeuserid.php
- templates/default/assets/fields/changeuserid.tpl.php
- templates/default/css/fields/changeuserid.css
- templates/default/js/fields/changeuserid.js
Если было лень читать:
Реклама #
Zau4man 1 год назад #
Имхо, стоит доработать поле, чтобы выбирать по комбинации ник|емайл
&$!#% 1 год назад #
Я не против. Можете дорабатывать.
Def 1 год назад #
круто!)
Loadырь 1 год назад #
Не очень. Любой гость может менять у любой записи автора на любого из существующих в базе даных. Так как ссылка ваш_site.site/changeuserid/change/тут_id_нужной_записи/тут_id_любого_пользователя/тут_системное_имя_типа_контента с передачей параметров без проверки вводимых данных, как минимум выдаст смену авторства у указанной записи в указанном типе контента на некоего Васю Пупкина. Ну, а если сменить автора записи на себя, то в последствии можно редактировать ее как душе угодно. В обшем надо доработать.
&$!#% 1 год назад #
А для чего по-вашему проверка на админа в начале каждого экшена?
nifigasse.ru/changeuserid/change/16/1/board
Loadырь 1 год назад #
А точно, админа, то я и не заметил. Извините, за «наезд». Обычно ещё вешают проверку csrf_token на подобные экшены, чтобы исключить неконтролируемые запросы, его у вас я и не заметил. Но и так сойдёт )).
Happy 1 год назад #
Была бы идеальным возможность дать права нескольким людям .
Саня 1 год назад #
Круто. Спасибо за то что делитесь такой информацией настолько подробно.
&$!#% 1 год назад #
Обновил. Расписывать нет времени, простите:
instantcms.ru/addons/changeuserid/view-addons-versions
На 2.16 не проверял, но должно работать.
CEH9I 1 год назад #
А возможно это поле заставить работать из админки при массовом редактировании записей? К примеру я хочу 100 записей передать другому человеку, каждому вручную заколебешься изменять авторство))
SEOrigin 1 год назад #
В админке такая опция есть по умолчанию. Выделите все записи, в верхнем меню кликните на пункт «Записи», затем «Изменить», там выберите поле «Автор», укажите ID автора и нажмите сохранить.
Ьascal 1 год назад #
Нет там возможности менять поле «Автор».
Гарри 1 год назад #
Сейчас проверил и всё там есть.
CEH9I 1 год назад #
Да есть
&$!#% 1 год назад #
v.1.0.2 — добавлена возможность отправлять уведомления новым авторам.
instantcms.ru/addons/changeuserid/view-addons-versions
Dark Space 1 год назад #
Нифигасее… ❤🌹🌸🌷💐
Сергей 1 год назад #
Читаю ваши посты с большим удовольствием, познавательно и разработки нужные, давно причём. Первый раз, возник маленький конфликт с установкой вашего поля, думаю не дружит оно со вкладками Александра DWD.
Notice: Undefined index: user_ap in /public_html/templates/default/content/rent_item.tpl.php on line 41 и так тоже: Notice: Undefined index: user_ap in / /public_html/templates/modern/content/rent_item.tpl.php on line 41 как бы ваше поле подружить со вкладками Александра? Буду очень признателен.
В типах контента где файлы DWD не используются, всё нормально работает.
&$!#% 1 год назад #
Удалите поле из типа контента. После этого откройте файл system/fileds/changeuserid.php/
замените на
удалите строку:
и перед этой строкой
добавьте
Добавьте заново поле в тип контента.
Сергей 1 год назад #
Всё случилось, как надо, заработало во вкладках без проблем. Благодарю за помощь, очень мужное поле.
Ьascal 1 год назад #
При создании поля ошибка 503 (на 2.13.1).
Ошибка в запросе БД:
У вас ошибка в синтаксисе SQL возле '' в строке 1
ALTER TABLE cms_con_news ADD `userid`
Последние вызовы:
modelContent->addContentField() @ /system/controllers/admin/actions/ctypes_fields_add.php: 50
actionAdminCtypesFieldsAdd->run() @ /system/core/controller.php: 585
cmsController->runExternalAction() @ /system/core/action.php: 37
cmsAction->__call() @ /system/controllers/admin/actions/ctypes.php: 11
actionAdminCtypes->run() @ /system/core/controller.php: 585
cmsController->runExternalAction() @ /system/core/controller.php: 456
cmsController->executeAction() @ /system/core/controller.php: 432
cmsController->runAction() @ /system/core/core.php: 786
cmsCore->runController() @ /index.php: 46
&$!#% 1 год назад #
Тогда, видимо, не работали виртуальные поля. Установите версию 1.0.3: instantcms.ru/addons/changeuserid/view-addons-versions
Ьascal 1 год назад #
Спасибо, теперь создаётся поле.