View source
<?php
define("NODE_LIMIT_NO_LIMIT", -1);
define("NODE_LIMIT_PERM_ADMIN", "administer node limits");
define("NODE_LIMIT_LIMIT_DOESNT_APPLY", 0);
define("NODE_LIMIT_LIMIT_DOES_APPLY", 1);
define("NODE_LIMIT_LIMIT_NEUTRAL", 2);
function node_limit_perm() {
return array(
NODE_LIMIT_PERM_ADMIN,
);
}
function node_limit_menu() {
$items = array();
$items['admin/user/node_limit'] = array(
'title' => t('Node Limits'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'node_limit_list_limits',
),
'access arguments' => array(
NODE_LIMIT_PERM_ADMIN,
),
);
$items['admin/user/node_limit/list'] = array(
'title' => t('List'),
'type' => MENU_DEFAULT_LOCAL_TASK,
'access arguments' => array(
NODE_LIMIT_PERM_ADMIN,
),
'weight' => -10,
);
$items['admin/user/node_limit/add'] = array(
'title' => t('Add Node Limit'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'node_limit_limit_form',
'0',
),
'access arguments' => array(
NODE_LIMIT_PERM_ADMIN,
),
'type' => MENU_LOCAL_TASK,
);
$items['admin/user/node_limit/%node_limit'] = array(
'title' => t('Edit Node Limit'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'node_limit_limit_form',
3,
),
'access arguments' => array(
NODE_LIMIT_PERM_ADMIN,
),
'type' => MENU_LOCAL_TASK,
);
$items['admin/user/node_limit/%node_limit/delete'] = array(
'title' => t('Delete Node Limit'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'node_limit_delete_form',
3,
),
'access arguments' => array(
NODE_LIMIT_PERM_ADMIN,
),
'type' => MENU_CALLBACK,
);
$items['admin/user/node_limit/%node_limit/clone'] = array(
'title' => t('Clone Node Limit'),
'page callback' => 'node_limit_clone_limit',
'page arguments' => array(
3,
),
'access arguments' => array(
NODE_LIMIT_PERM_ADMIN,
),
'type' => MENU_CALLBACK,
);
return $items;
}
function node_limit_theme() {
return array(
'node_limit_limit_form' => array(
'arguments' => array(
'form' => NULL,
),
),
'node_limit_list_limits' => array(
'arguments' => array(
'form' => NULL,
),
),
);
}
function node_limit_nodeapi($node, $op, $a3 = NULL, $a4 = NULL) {
if ($op == 'prepare' || $op == 'validate') {
if ($node->nid == 0 && _node_limit_violates_limit($node)) {
$nodetypename = node_get_types('name', $node);
drupal_set_message(t("You can't create more content of type !type", array(
'!type' => $nodetypename,
)), 'error');
drupal_goto('node/add');
}
}
}
function _node_limit_violates_limit($node) {
if ($node->uid == 1) {
return FALSE;
}
$limits = node_limit_limits($node);
foreach ($limits as $idx => $lid) {
$limit = node_limit_load($lid);
if ($limit['nlimit'] == NODE_LIMIT_NO_LIMIT) {
continue;
}
$sql = _node_limit_sql($limit['lid']);
$count = db_result(db_query($sql));
if ($count >= $limit['nlimit']) {
return TRUE;
}
}
return FALSE;
}
function _node_limit_sql($lid) {
$sql = "SELECT COUNT(n.nid) AS number FROM {node} AS n";
$components = module_invoke_all('node_limit_sql', $lid);
$limit = node_limit_load($lid);
$joins = isset($components['join']) ? implode(' ', $components['join']) : '';
$wheres = isset($components['where']) ? 'WHERE ' . implode(' AND ', $components['where']) : '';
return $sql . ' ' . $joins . ' ' . $wheres;
}
function node_limit_limits($node) {
$user = user_load($node->uid);
$res = db_query("SELECT lid FROM {node_limit} ORDER BY weight ASC");
$applicable_limits = array();
while ($l = db_fetch_array($res)) {
$lid = $l['lid'];
$applies = TRUE;
$submodule_applies = module_invoke_all('node_limit_applies_in_context', $lid, $node, $user);
foreach ($submodule_applies as $module => $module_applies) {
if ($module_applies == NODE_LIMIT_DOESNT_APPLY) {
$applies = FALSE;
}
}
if ($applies == TRUE) {
$applicable_limits[] = $lid;
}
}
return $applicable_limits;
}
function theme_node_limit_list_limits($form) {
$header = array(
t('Title'),
t('Limit'),
t('Weight'),
t('Actions'),
);
$rows = array();
foreach (element_children($form['limits']) as $lid) {
$row = array();
$form['limits'][$lid]['weight']['#attributes']['class'] = 'node_limit-weight';
$row[] = drupal_render($form['limits'][$lid]['title']);
$row[] = drupal_render($form['limits'][$lid]['nlimit']);
$row[] = drupal_render($form['limits'][$lid]['weight']);
$row[] = drupal_render($form['limits'][$lid]['actions']);
$rows[] = array(
'data' => $row,
'class' => 'draggable',
);
}
if (count($rows) > 0) {
$out = theme('table', $header, $rows, array(
'id' => 'node_limit-table',
));
}
$out .= drupal_render($form);
drupal_add_tabledrag('node_limit-table', 'order', 'sibling', 'node_limit-weight');
return $out;
}
function node_limit_list_limits() {
$weights = array();
for ($i = -10; $i <= 10; $i++) {
$weights[$i] = $i;
}
$form = array(
'#tree' => TRUE,
);
$form['limits'] = array();
$sql = "SELECT * FROM {node_limit} ORDER BY weight ASC";
$res = db_query($sql);
$limit_count = 0;
while ($rec = db_fetch_array($res)) {
$limit_count++;
$form['limits'][$rec['lid']]['weight'] = array(
'#type' => 'select',
'#options' => $weights,
'#default_value' => $rec['weight'],
);
$form['limits'][$rec['lid']]['title'] = array(
'#value' => $rec['title'],
);
$form['limits'][$rec['lid']]['nlimit'] = array(
'#value' => $rec['nlimit'],
);
$form['limits'][$rec['lid']]['actions'] = array(
'#value' => l(t('Edit'), 'admin/user/node_limit/' . $rec['lid']) . ' ' . l(t('Delete'), 'admin/user/node_limit/' . $rec['lid'] . '/delete') . ' ' . l(t('Clone'), 'admin/user/node_limit/' . $rec['lid'] . '/clone'),
);
}
if ($limit_count > 0) {
$form['save'] = array(
'#type' => 'submit',
'#value' => t('Save Limits'),
);
}
else {
$form['create'] = array(
'#value' => l(t('Add a new node limit'), 'admin/user/node_limit/add'),
);
}
return $form;
}
function node_limit_list_limits_submit($form_id, &$form_state) {
$sql = "UPDATE {node_limit} SET `weight`='%d' WHERE `lid`='%d'";
foreach ($form_state['values']['limits'] as $lid => $info) {
db_query($sql, $info['weight'], $lid);
}
drupal_set_message(t('Limits saved!'));
}
function theme_node_limit_limit_form($form) {
if (!isset($form['info'])) {
return;
}
$rows = array();
foreach ($form['node_limit_elements'] as $module => &$element) {
if (is_array($element['applies']) && is_array($element['element'])) {
if ($element['element']['#custom_render'] === TRUE && module_hook($module, 'node_limit_render_element')) {
$func = $module . '_node_limit_render_element';
$rendered_element = $func($element['element']);
}
else {
$rendered_element = drupal_render($element['element']);
}
$rows[] = array(
drupal_render($element['applies']),
$rendered_element,
);
}
}
$output = drupal_render($form['info']);
if (count($rows) > 0) {
$output .= theme('table', array(
t('Applies to:'),
'',
), $rows);
}
$output .= drupal_render($form);
return $output;
}
function node_limit_limit_form(&$form_state, $limit) {
if ($limit == FALSE) {
$limit = array();
}
$form = array();
$form['#tree'] = TRUE;
if ($limit['lid'] > 0) {
$form['lid'] = array(
'#type' => 'hidden',
'#value' => $limit['lid'],
);
}
$form['info']['title'] = array(
'#title' => t('Description'),
'#type' => 'textfield',
'#default_value' => $limit['title'],
'#required' => TRUE,
'#description' => t('The description for this Node Limit'),
);
$form['info']['nlimit'] = array(
'#title' => t('Limit'),
'#type' => 'textfield',
'#default_value' => isset($limit['nlimit']) ? $limit['nlimit'] : NODE_LIMIT_NO_LIMIT,
'#size' => 10,
'#required' => TRUE,
'#description' => t('The number of nodes for this limit. Must be an integer greater than 0 or %nolimit for no limit', array(
'%nolimit' => NODE_LIMIT_NO_LIMIT,
)),
);
$form['info']['weight'] = array(
'#type' => 'hidden',
'#value' => $limit['weight'],
);
$elements = module_invoke_all('node_limit_element', $limit['lid']);
$form['node_limit_elements'] = array();
foreach ($elements as $module => $element) {
$form['node_limit_elements'][$module]['applies'] = array(
'#type' => 'checkbox',
'#title' => $element['#title'],
'#default_value' => isset($limit[$module]),
);
$element['#title'] = '';
$form['node_limit_elements'][$module]['element'] = $element;
}
$form['save'] = array(
'#type' => 'submit',
'#value' => $limit['lid'] > 0 ? t('Edit Node Limit') : t('Add Node Limit'),
);
return $form;
}
function node_limit_limit_form_validate($form_id, &$form_state) {
if (!is_numeric($form_state['values']['info']['nlimit'])) {
form_set_error('info][limit', t('Node limits must be an integer'));
}
else {
if (intval($form_state['values']['info']['nlimit']) != floatval($form_state['values']['info']['nlimit'])) {
form_set_error('info][limit', t('Node limits must be an integer'));
}
else {
if (intval($form_state['values']['info']['nlimit']) < NODE_LIMIT_NO_LIMIT) {
form_set_error('info][limit', t('Node limits cannot be less that %nolimit', array(
'%nolimit' => NODE_LIMIT_NO_LIMIT,
)));
}
}
}
if (trim($form_state['values']['info']['title']) == '') {
form_set_error('info][title', t('Invalid Node Limit title'));
}
foreach ($form_state['values']['node_limit_elements'] as $module => $element) {
if ($element['applies'] === 1) {
$result = module_invoke($module, 'node_limit_element_validate', $element['element']);
if (is_array($result) && isset($result['error'])) {
$path = $module . '][element';
if (isset($result['element'])) {
$path .= '][' . $result['element'];
}
form_set_error('node_limit_elements][' . $path, $result['error']);
}
}
}
}
function node_limit_limit_form_submit($form_id, &$form_state) {
if (isset($form_state['values']['lid'])) {
$lid = $form_state['values']['lid'];
}
else {
$lid = _node_limit_next_limit_id();
}
$limit = array();
$limit['lid'] = $lid;
$limit['nlimit'] = intval($form_state['values']['info']['nlimit']);
$limit['title'] = $form_state['values']['info']['title'];
$limit['weight'] = $form_state['values']['info']['weight'];
foreach ($form_state['values']['node_limit_elements'] as $module => $element) {
if ($element['applies']) {
$limit[$module] = $element['element'];
}
}
node_limit_save($limit);
$form_state['redirect'] = 'admin/user/node_limit';
drupal_set_message(t('Saved limit "%limit"', array(
'%limit' => $limit['title'],
)));
}
function node_limit_delete_form(&$form_state, $limit) {
if ($limit == FALSE) {
drupal_goto('admin/user/node_limit');
}
$form = array(
'lid' => array(
'#type' => 'hidden',
'#value' => $limit['lid'],
),
);
return confirm_form($form, t('Are you sure you want to delete %name?', array(
'%name' => $limit['title'],
)), 'admin/user/node_limit');
}
function node_limit_delete_form_submit($form_id, &$form_state) {
$lid = $form_state['values']['lid'];
node_limit_delete($lid);
$form_state['redirect'] = 'admin/user/node_limit';
}
function node_limit_clone_limit($limit) {
$old_title = $limit['title'];
$limit['lid'] = _node_limit_next_limit_id();
$limit['title'] = t('Clone of !title', array(
'!title' => $old_title,
));
node_limit_save($limit);
drupal_set_message(t('Cloned limit "%limit"', array(
'%limit' => $old_title,
)));
drupal_goto('admin/user/node_limit');
}
function _node_limit_next_limit_id() {
$next_lid = db_result(db_query("SELECT (MAX(lid)+1) AS lid FROM {node_limit}"));
return max($next_lid, 1);
}
function node_limit_load($lid) {
if (!is_numeric($lid)) {
return FALSE;
}
$info = db_fetch_array(db_query("SELECT * FROM {node_limit} WHERE `lid`='%d'", $lid));
if ($info['lid'] == $lid && intval($lid) >= 0) {
$res = module_invoke_all('node_limit_load', $lid);
return array_merge($info, $res);
}
else {
return FALSE;
}
}
function node_limit_delete($lid) {
db_query("DELETE FROM {node_limit} WHERE `lid`='%d'", $lid);
module_invoke_all('node_limit_delete', $lid);
}
function node_limit_save($limit) {
node_limit_delete($limit['lid']);
db_query("INSERT INTO {node_limit} VALUES('%d', '%d', '%s', '%d')", $limit['lid'], $limit['nlimit'], $limit['title'], $limit['weight']);
drupal_set_message(print_r($limit, true));
$modules = module_implements('node_limit_save');
foreach ($modules as $module) {
module_invoke($module, 'node_limit_save', $limit['lid'], isset($limit[$module]), $limit[$module]);
}
}