Создайте новое удаление object_action в администраторе Symfony 1.4 - PullRequest
3 голосов
/ 28 января 2010

Я использую генератор администратора Symfony 1.4 / Doctrine.

Есть список вопросов, и я хотел бы иметь возможность выполнить пользовательскую object_action для каждого из них.

То, что я ищу, - это имитировать действие объекта _delete, но перед этим нужно выполнить некоторые вычисления.

Итак, я создал новое действие:

  public function executeListDeleteAndRecalculate(sfWebrequest $request)
  {
    // Do the calculation

    // Then delete the question
  }

И я добавляю его в мой generator.yml:

object_actions:
    delete_and_recalculate: ~

новое действие отображается в генераторе администратора, но часть удаления не работает.

Я попробовал несколько вещей, чтобы это заработало:

  • Как только все вычисления были выполнены, я сначала попытался перенаправить на действие questionActions/delete.
  • Я также пытался скопировать код executeDelete в мое новое действие.

Но каждый раз, когда я получаю печально известную

500 | Внутренняя ошибка сервера | sfValidatorErrorSchema _csrf_token [Обязательно.]

Так что я предполагаю, что Symfony совершает магию перед тем, как удалить объект.

Знаете ли вы, что мне не хватает, и , как лучше всего реализовать действие типа deleteAndRecalculate?

Edit:

Конечно, если я уберу $request->checkCSRFProtection();, все будет работать нормально. Но я предполагаю, что это очень важно, поэтому я хотел бы найти более красивое решение.

1 Ответ

4 голосов
/ 28 января 2010

Это связано с тем, что ссылка delete от генератора администратора использует токен для предотвращения атак CSRF.

По сути, он устанавливает токен в вашу сессию и в скрытое поле формы, а затем проверяет их друг против друга по запросу. Это возможно, потому что ссылка delete в генераторе администратора является формой (сгенерированной javascript) (это делается для добавления скрытого поля sf_method для имитации поведения REST).

Для получения дополнительной информации о том, как CSRF работает и может быть предотвращено, вы можете прочитать далее в Википедии: http://en.wikipedia.org/wiki/Cross-site_request_forgery

Что вы можете сделать, так это использовать ссылку такого же типа, вам просто нужно передать параметр method в link_to, чтобы он сгенерировал форму, посмотрите на lib/generator/sfModelGeneratorHelper.class.php строку 32, чтобы увидеть, как это делается в админ-ген.

Затем вы выполните $request->checkCSRFProtection() в вашем методе executeDeleteAndRecalculate и продолжите все, что вы хотите сделать, включая удаление объекта вручную.

Чтобы правильно сгенерировать ссылку, вы должны добавить метод linkToDeleteAndRecalculate в класс Helper вашего модуля (который должен находиться в файле lib/${YourModule}GeneratorHelper.class.php вашего каталога модулей) и добавить следующий код (непосредственно взятый и адаптированный из sfModelGeneratorHelper):

public function linkToDeleteAndRecalculate($object, $params)
{
  if ($object->isNew())
  {
    return '';
  }

  return '<li class="sf_admin_action_delete">'.link_to(__($params['label'], array(), 'sf_admin'), 'delete_and_recalculate', $object, array('method' => 'delete', 'confirm' => !empty($params['confirm']) ? __($params['confirm'], array(), 'sf_admin') : $params['confirm'])).'</li>';
}

Обратите внимание, что вы должны изменить маршрут (я поставил delete_and_recalculate по умолчанию, но вы можете добавить его к имени вашего модуля) из вызова link_to.

Затем вы можете использовать ваш delete_and_recalculate почти как встроенный метод из генератора администратора (и передать ему метку из generator.yml, например)

Теперь это был трудный путь.

Самый простой способ - подписаться на событие admin.delete_object, например, от предварительного выполнения вашего модуля и до вашей работы: -)

...