Drupal で、カウンタを作ってみた。

なぜか Drupal にありそうでないのがカウンタ。いまどきカウンタなんて・・・などという声が聞こえてきそうだが、Google Analytics でアクセスログ取っていてもカウンタは欲しかったんですよ。自分のブログ継続モチベーション維持のために(苦笑)。なさそうなのでなので作ってみた。 モジュールを作っていて、データベースにテーブルをわざわざ作ってそれを利用するまでもないことに気づいた。カウンタって状態保持の変数だから、variable_set / variable_get で十分だろう(私も最初はテーブルに記録していましたが、たかだが1レコードしか使わないことが判明。variable_set / variable_get に変えました。もしそれがイヤなら、改造してください)。

このモジュールを有効にすると、counter_display() という関数を提供するので、テンプレートやブロックなど、Drupal でコードが書けるところなら好きなところで呼び出すことができる。

  1. ファイルをダウンロード、または、以下の3つのファイルをモジュールの counter ディレクトリに保存。
  2. まずは以下のコードを counter.info として保存。 ; $Id: counter.info,v 5.x-0.6 2008/04/30 00:00:00 yas Exp $ name = Counter description = "Simple Counter." package = version = VERSION ; Information added by drupal.org packaging script on 2008-04-30 version = "5.x-0.6" project = "Counter"
  3. 次のコードを counter.install として保存。 <?php // $Id: counter.install,v 5.x-0.6 2008/04/30 00:00:00 yas Exp $ /** * Implementation of hook_install(). */ function counter_install() { switch ($GLOBALS['db_type']) { <pre>case 'mysql': case 'mysqli': break; case 'pgsql': break; } } /** * Implementation of hook_uninstall(). */ function counter_uninstall() { variable_del('counter_deny'); variable_del('counter_check'); variable_del('counter_interval'); variable_del('counter_lastip'); variable_del('counter_lasttime'); variable_del('counter_checkpoint'); variable_del('counter_checkpoint_interval'); variable_del('counter_checkpoint_time'); } ?>
  4. 次のコードを counter.module として保存。 <?php // $Id: counter.module,v 5.x-0.6 2008/04/30 00:00:00 yas Exp $ // updated by yas 2008/04/30 // updated by yas 2008/04/23 // updated by yas 2008/04/22 // updated by yas 2008/04/06 // updated by yas 2008/04/05 // updated by yas 2007/12/15 // updated by yas 2007/12/03 // created by yas 2007/12/03 /** * Implementation of hook_help() * Display help text for the zone module */ define('MODULE_NAME', 'Counter'); define('DENY_IP', "64.233.*.*\n66.249.*.*"); define('PRIVILEGE_ADMIN' , 'administer settings'); // define('PRIVILEGE_VIEW' , 'view counter'); function counter_help($section) { switch ($section) { <pre>case 'admin/help#counter': $o .= '<p>' . t('Simple counter') . '</p>'; return $o; case 'admin/modules#description': return t('Simple counter.'); } } /** * Implementation of hook_perm(). * Define the permissions this module uses */ function counter_perm() { return array(PRIVILEGE_ADMIN); } /** * Implementation of hook_access(). */ function counter_access($op, $node) { // global $user; // // if ($op == 'view') { // return user_access(PRIVILEGE_VIEW); // } } /** * Implementation of hook_menu(). */ function counter_menu($may_cache) { $items = array(); if ($may_cache) {
    $items[] = array(
      'type'               => MENU_NORMAL_ITEM,
      'path'               => 'admin/settings/counter',
      'title'              => t(MODULE_NAME),
      'access'             => user_access(PRIVILEGE_ADMIN),
      'callback'           => 'drupal_get_form',
      'callback arguments' => 'counter_admin',
      'description'        => 'Configure counter settings'
    );
    
    } return $items; } /** * Implementation of hook_admin(). */ function counter_admin() { // Robot IP Addresses $form['counter_deny'] = array(
    '#type'          => 'textarea',
    '#title'         => t('Robot IP Addresses'),
    '#default_value' => variable_get('counter_deny', DENY_IP),
    '#cols'          =>  20,
    '#rows'          =>   5,
    '#weight'        => -10,
    '#required'      => TRUE
    
    ); // IP check $form['counter_check'] = array(
    '#type'          => 'checkbox',
    '#title'         => t('Check by a sequential IP Address'),
    '#default_value' => variable_get('counter_check', 1),
    '#required'      => FALSE
    
    ); // Current total $form['counter_total'] = array(
    '#type'          => 'textfield',
    '#title'         => t('Set a counter'),
    '#default_value' => variable_get('counter_total', 0),
    '#size'          => 10,
    '#maxlength'     => 10,
    '#required'      => TRUE
    
    ); // sequential access check interval global $user; $timezone = $user->timezone; $form['counter_checkpoint'] = array(
    '#type' => 'item',
    '#title' => t('Last Checkpoint Count') . ' (' . gmdate('Y/m/d H:i', (variable_get('counter_checkpoint_time', time()) + $timezone)) . ')',
    '#value' => number_format(variable_get('counter_checkpoint', 0)),
    
    ); // Last IP address $form['counter_lastip'] = array(
    '#type'          => 'textfield',
    '#title'         => t('Last IP address'),
    '#default_value' => variable_get('counter_lastip', ''),
    '#size'          => 20,
    '#maxlength'     => 15,
    '#required'      => FALSE
    
    ); // sequential access check interval $form['counter_interval'] = array(
    '#type'          => 'textfield',
    '#title'         => t('Minimum interval (min) with the same IP address'),
    '#default_value' => variable_get('counter_interval', 5),
    '#size'          => 3,
    '#maxlength'     => 3,
    '#required'      => FALSE
    
    ); $checkpoint_intervals = drupal_map_assoc(array(600, 900, 1800, 3600, 10800, 21600, 43200, 86400, 172800, 259200, 604800), 'format_interval'); // sequential access check interval $form['counter_checkpoint_interval'] = array(
    '#type'          => 'select',
    '#options'       => $checkpoint_intervals,
    '#title'         => t('Interval for the checkpoint'),
    '#default_value' => variable_get('counter_checkpoint_interval', 86400),
    '#required'      => TRUE
    
    ); return system_settings_form($form); } function counter_init() { $total = variable_get('counter_total' , 0); $is_check = variable_get('counter_check' , 1); $lastip = variable_get('counter_lastip' , ''); $interval = variable_get('counter_interval', 5); $lasttime = variable_get('counter_lasttime', 0); $lastchecktime = variable_get('counter_checkpoint_time', 0); $lastcheckpoint = variable_get('counter_checkpoint' , 0); $checkpoint_interval = variable_get('counter_checkpoint_interval', 86400); $now = time(); $deny = split("[\n\|,]", variable_get('counter_deny', DENY_IP)); $deny = implode(')|(', $deny); $deny = str_replace('*', '\d+', $deny); $deny = str_replace('.', '\.' , $deny); $ip = $_SERVER['REMOTE_ADDR']; if(!preg_match ("/($deny)/i", $ip)) {
    if(($is_check && $lastip != $ip)
    || ($is_check && $lastip == $ip && (($now - $lasttime) > $interval * 60))
    || !$is_check) {
      $total =   $total >= $lastcheckpoint
             ? ++$total
             : ++$total + $lastcheckpoint;
      variable_set('counter_total'   , $total);
      variable_set('counter_lasttime', $now);
      variable_set('counter_lastip'  , $ip);
    
      if(($now - $lastchecktime) > $checkpoint_interval
      && $total > $lastcheckpoint) {
        variable_set('counter_checkpoint'     , $total);
        variable_set('counter_checkpoint_time', $now);
      }
    }
    
    } } function counter_display() { return number_format(variable_get('counter_total', 0)); } ?>
  5. 上のコードは、template.php で、page.tpl.php その他テンプレートから $counter という変数で、カウンタの数字が呼び出せる。テンプレートで <?php print $counter; ?> というコードを入れれば、カウンタが表示される。
  6. また、ブロックでは、以下の1行を書いたブロックを追加すれば、カウンタがブロックに表示される。 <?php if(module_exists('counter')) { return counter_display(); } ?>
  7. ちなみに、https://yourdomain.com/admin/settings/counter でカウンタの設定ができるようになってます。Google のロボットからのアクセスは予めはじくようにしています。