class BotchaRecipebook in BOTCHA Spam Prevention 6.3
Same name and namespace in other branches
- 6.2 controller/botcha_recipebook.controller.inc \BotchaRecipebook
- 7.2 controller/botcha_recipebook.controller.inc \BotchaRecipebook
- 7.3 controller/recipebook/botcha.recipebook.controller.inc \BotchaRecipebook
Hierarchy
- class \BotchaRecipebook
Expanded class hierarchy of BotchaRecipebook
File
- controller/
recipebook/ botcha.recipebook.controller.inc, line 76 - Controller layer of the BotchaRecipebook objects.
View source
class BotchaRecipebook {
/**
* Identifier of the recipe book.
*/
public $id;
/**
* A title of the book.
*/
public $title;
/**
* Description of the recipe book.
*/
public $description;
/**
* List of recipe ids.
* It is not set by default to let the application to determine whether it is
* not set yet or it is set and empty.
* @var BotchaRecipe
*/
//protected $recipes = array();
protected $recipes;
/**
* List of form ids.
* It is not set by default to let the application to determine whether it is
* not set yet or it is set and empty.
* @var BotchaForm
*/
//protected $forms = array();
protected $forms;
public function __construct($id) {
$this->id = $id;
}
public function isApplicable($form, $form_state) {
$form_id = $form['form_id']['#value'];
$isApplicable = FALSE;
if (!user_access('skip BOTCHA')) {
$isApplicable = TRUE;
}
switch ($form_id) {
case 'user_register':
// Only change the registration form. There is also 'user_register' form
// at /admin/user/user/create path, but we leave it alone.
if (FALSE === strpos($form['#action'], 'user/register')) {
if (!variable_get('botcha_allow_on_admin_pages', FALSE)) {
$isApplicable = FALSE;
}
}
break;
}
return $isApplicable;
}
public function setTitle($title) {
$this->title = $title;
return $this;
}
public function getTitle() {
return $this->title;
}
public function setDescription($description) {
$this->description = $description;
return $this;
}
public function getDescription() {
return $this->description;
}
public function setRecipe($recipe_id) {
$this->recipes[$recipe_id] = $recipe_id;
return $this;
}
public function unsetRecipe($recipe_id) {
unset($this->recipes[$recipe_id]);
return $this;
}
/**
* @todo BotchaRecipebook getRecipes Description.
* @return array
*/
public function getRecipes() {
if (!isset($this->recipes)) {
$rs = BotchaModel::getRecipebooksRecipes(array(
'mode' => 'recipe',
'recipebooks' => $this->id,
));
foreach ($rs as $recipe_id) {
$this
->setRecipe($recipe_id);
}
}
return (array) $this->recipes;
}
public function setForm($form_id) {
$this->forms[$form_id] = $form_id;
return $this;
}
public function unsetForm($form_id) {
unset($this->forms[$form_id]);
return $this;
}
/**
* @todo BotchaRecipebook getForms Description.
* @return BotchaForm
*/
public function getForms() {
if (!isset($this->forms)) {
$fs = BotchaModel::getRecipebooksForms(array(
'mode' => 'form',
'recipebooks' => $this->id,
));
foreach ($fs as $form_id) {
$this
->setForm($form_id);
}
}
return (array) $this->forms;
}
/**
* Handle form depending on the result of spam check.
*
* @param string $result
* This parameter is string and not boolean to have a chance to easily implement
* new results of spam check (such as 'postponed', 'suspected' or other).
* @param array $form
* @param array $form_state
* @param array $is_spam
*/
public function handle($result, $form, $form_state, $is_spam) {
$recipes_spam = array_intersect($is_spam, array_fill_keys(array_keys($is_spam), TRUE));
$recipes_spam_count = count($recipes_spam);
$recipes_success = array_intersect($is_spam, array_fill_keys(array_keys($is_spam), FALSE));
$recipes_success_count = count($recipes_success);
// !!~ @todo Recipebook handle Reduce code duplication.
switch ($result) {
case 'success':
variable_set('botcha_form_passed_counter', $recipes_success_count);
// Show good submissions in log.
if (BOTCHA_LOGLEVEL >= 3) {
watchdog(BOTCHA_LOG, '!form_id post approved by BOTCHA.!more', array(
'!form_id' => $form['form_id']['#value'],
'!more' => '' . (BOTCHA_LOGLEVEL >= 3 ? ' Checked ' . count($this
->getRecipes()) . ' botchas (' . join(', ', $this
->getRecipes()) . ').' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . 'POST=<pre>' . print_r(_botcha_filter_form_values_log($_POST), 1) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . 'GET=<pre>' . print_r(_botcha_filter_form_values_log($_GET), 1) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . 'SERVER=<pre>' . print_r($_SERVER, 1) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . ' form=<pre>' . print_r(_botcha_filter_form_log($form), 1) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . ' values=<pre>' . print_r(_botcha_filter_form_values_log($form_state['values']), 1) . '</pre>' : ''),
), WATCHDOG_INFO);
}
$rules_event_name = 'botcha_form_approved';
break;
case 'spam':
default:
variable_set('botcha_form_blocked_counter', $recipes_spam_count);
// Show blocked submissions in log.
// @todo Turn logging into a Rules action.
if (BOTCHA_LOGLEVEL >= 1) {
watchdog(BOTCHA_LOG, '!form_id post blocked by BOTCHA: submission looks like from a spambot.!more', array(
'!form_id' => $form['form_id']['#value'],
'!more' => '' . (BOTCHA_LOGLEVEL >= 2 ? '<br /><br />' . 'Failed ' . $recipes_spam_count . ' of ' . count($this
->getRecipes()) . ' recipes [' . implode(', ', array_keys($recipes_spam)) . '] from "' . $this->id . '" recipe book.' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . 'POST=<pre>' . print_r(_botcha_filter_form_values_log($_POST), 1) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . 'GET=<pre>' . print_r(_botcha_filter_form_values_log($_GET), 1) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . 'SERVER=<pre>' . print_r($_SERVER, 1) . '</pre>' : '') . (BOTCHA_LOGLEVEL >= 5 ? '<br /><br />' . ' values=<pre>' . print_r(_botcha_filter_form_values_log($form_state['values']), 1) . '</pre>' : ''),
), WATCHDOG_WARNING);
}
$rules_event_name = 'botcha_form_rejected';
break;
}
// Invoke rules event.
if (module_exists('rules')) {
$arguments = array(
// 'form' => &$form,
// 'form_state' => &$form_state,
'form_id' => $form['form_id']['#value'],
'total_recipes' => count($this
->getRecipes()),
'passed_recipes' => $recipes_success_count,
'passed_recipes_names' => join(', ', array_keys($recipes_success)),
// !!~ @todo Add last recipe name.
//'last_recipe_name' => $recipe->name,
// !!~ @todo Add a reason of fail to rules event invokation.
//'fail' => $fail,
'fail' => 'FAIL',
'failed_field' => 'mail',
);
// !!? Do we need per recipe rules event invoking?
rules_invoke_event($rules_event_name, $arguments);
}
}
/**
* Spam check.
* Currently the logic is as follows: if we could find a recipe that failed
* spam check - then we consider this form submission as spam and decline it.
*
* @param array $form
* @param array $form_state
* @param array $is_spam
* @return boolean
*/
public function isSpam($form, $form_state, $is_spam) {
// Consider form submission as a spam if at least one recipe considered it
// as a spam.
return count($is_spam) ? (bool) array_diff($is_spam, array_fill(0, count($is_spam), FALSE)) : FALSE;
}
public function apply(&$form, &$form_state) {
// @todo Abstract it.
// '#input'=1 hacks FAPI to call #process handler on the form.
$form += array(
'#input' => TRUE,
);
$form['#process'][] = 'botcha_fprocess';
//$form_state['no_cache'] = TRUE;
// User_login forms open session in validate hooks instead of submit,
// we should be the first to validate - add our hook to the beginning.
if (is_array($form['#validate'])) {
// Workaround since array_unshift'ing by reference was deprecated.
// @link http://www.php.net/manual/en/function.array-unshift.php#40270 @endlink
array_unshift($form['#validate'], '');
$form['#validate'][0] = 'botcha_formValidate';
}
else {
$form['#validate'] = array(
'botcha_formValidate',
);
}
// @todo ?Do we need it?
$form_state['#botcha'] = $this->id;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
BotchaRecipebook:: |
public | property | Description of the recipe book. | |
BotchaRecipebook:: |
protected | property | ||
BotchaRecipebook:: |
public | property | Identifier of the recipe book. | |
BotchaRecipebook:: |
protected | property | ||
BotchaRecipebook:: |
public | property | A title of the book. | |
BotchaRecipebook:: |
public | function | ||
BotchaRecipebook:: |
public | function | ||
BotchaRecipebook:: |
public | function | @todo BotchaRecipebook getForms Description. | |
BotchaRecipebook:: |
public | function | @todo BotchaRecipebook getRecipes Description. | |
BotchaRecipebook:: |
public | function | ||
BotchaRecipebook:: |
public | function | Handle form depending on the result of spam check. | |
BotchaRecipebook:: |
public | function | ||
BotchaRecipebook:: |
public | function | Spam check. Currently the logic is as follows: if we could find a recipe that failed spam check - then we consider this form submission as spam and decline it. | |
BotchaRecipebook:: |
public | function | ||
BotchaRecipebook:: |
public | function | ||
BotchaRecipebook:: |
public | function | ||
BotchaRecipebook:: |
public | function | ||
BotchaRecipebook:: |
public | function | ||
BotchaRecipebook:: |
public | function | ||
BotchaRecipebook:: |
public | function | 1 |