放牧代码和思想
专注自然语言处理、机器学习算法
    This thing called love. Know I would've. Thrown it all away. Wouldn't hesitate.

Chapter 07: Working with Nodes 使用节点

Drupal灵活的节点类型,对应Drupal7专业开发指南 第三版的的七章源码:

job_post.info

name = Job Post
description = A job posting content type
package = Pro Drupal Development
core = 7.x
files[] = job_post.install
files[] = job_post.module

job_post.install

<?php
 
/**
* @file
* Install file for Job Post module.
*/
/**
 * Implements hook_install().
 * - Add the body field.填充body字段
 * - Configure the body field.配置body 字段
 * - Create the company name field.创建公司名称字段
 */
function job_post_install()
{
    // 更新 节点类型的数据库缓存.在写一个新的模块的是时候,若要涉及到节点类型的创建,这个函数必须要调用一下.
    node_types_rebuild();
    // 获取所有可用的节点类型
    $types = node_type_get_types();
    // add the body field to the node type
    // 为一个内容类型增加一个body 字段
    node_add_body_field($types['job_post']);
    // Load the instance definition for our content type's body
    // Returns an array of instance data for a specific field and bundle.
    // 返回字段在数据库中的实例
    $body_instance = field_info_instance('node', 'body', 'job_post');
    // Configure the body field
    // 配置body字段
    $body_instance['type'] = 'text_summary_or_trimmed';
    // Save our changes to the body field instance.
    // 保存修改
    field_update_instance($body_instance);
    // Create all the fields we are adding to our content type.
    // 创建这个类容类型
    foreach(_job_post_installed_fields() as $field)
    {
        field_create_field($field);
    }
    // Create all the instances for our fields.
    // 创建实例
    foreach(_job_post_installed_instances() as $instance)
    {
        $instance['entity_type'] = 'node';
        $instance['bundle'] = 'job_post';
        field_create_instance($instance);
    }
}
 
/**
 * Return a structured array defining the fields created by this content type.
 * For the job post module there is only one additional field – the company name
 * Other fields could be added by defining them in this function as additional
 * elements
 * in the array below
 * 返回字段数组
 */
function _job_post_installed_fields()
{
    // 返回值是翻译函数的名字。get_t()函数常用于Drupal安装期间所使用的钩子hook_install(),也可以在安装模块时使用。
    $t = get_t();
    return array(
            'job_post_company' => array(
                    'field_name' => 'job_post_company',
                    'label' => $t('Company posting the job listing'),
                    'type' => 'text'
            ) 
    );
}
 
/**
 * Return a structured array defining the field instances associated with this
 * content type.
 * 返回实例数组
 */
function _job_post_installed_instances()
{
    $t = get_t();
    return array(
            'job_post_company' => array(
                    'field_name' => 'job_post_company',
                    'type' => 'text',
                    'label' => $t('Company posting the job listing'),
                    'widget' => array(
                            'type' => 'text_textfield'
                    ),
                    'display' => array(
                            'example_node_list' => array(
                                    'label' => $t('Company posting the job listing'),
                                    'type' => 'text'
                            ) 
                    ) 
            ) 
    );
}
 
/**
 * Implements hook_uninstall().
 * 卸载
 */
function job_post_uninstall()
{
    // Gather all the example content that might have been created while this
    // module was enabled.
    // 收集所有可能创建的类容
    $sql = 'SELECT nid FROM {node} n WHERE n.type = :type';
    $result = db_query($sql, array(
            ':type' => 'job_post'
    ));
    $nids = array();
    foreach($result as $row)
    {
        $nids[] = $row->nid;
    }
    // Delete all the nodes at once
    // 删除所有节点
    node_delete_multiple($nids);
    // Loop over each of the fields defined by this module and delete
    // all instances of the field, their data, and the field itself.
    // 遍历所有模块定义的字段然后删除之
    foreach(array_keys(_job_post_installed_fields()) as $field) // 函数返回包含数组中所有键名的一个新数组。
    {
        field_delete_field($field); // 通过fieldname指定一个字段的实例和数据以供删除
    }
    // Loop over any remaining field instances attached to the job_post
    // content type (such as the body field) and delete them individually.
    // 删除与其有关的类容类型然后单独删除它们
    $instances = field_info_instances('node', 'job_post');
    foreach($instances as $instance_name=>$instance)
    {
        field_delete_instance($instance); // 通过instance指定一个字段的实例和数据以供删除
    }
    // Delete our content type
    // 删除类容类型
    node_type_delete('job_post');
    // Purge all field infromation
    // 批量删除,最大大小1000
    field_purge_batch(1000);
}

job_post.module

<?php
/**
* @file
* This module provides a node type called job post
*/
/**
 * Implements hook_node_info() to provide our job_post type.
 * 当Drupal查找可用可用的节点类型时用到
 */
function job_post_node_info() {
    return array(
            'job_post' => array(
                    'name' => t('Job Post'),
                    'base' => 'job_post',
                    'description' => t('Use this content type to post a job.'),
                    'has_title' => TRUE,
                    'title_label' => t('Job Title'),
                    'help' => t('Enter the job title, job description, and the name of the company that posted the job'),
            ),
    );
}
/**
 * Implements hook_menu_alter().
 * 实现只有站点管理员才能使用这项功能
 */
function job_post_menu_alter(&$callbacks)
{
    // If the user does not have 'administer nodes' permission,
    // disable the job_post menu item by setting its access callback to FALSE.
    // 如果没有权限,通过禁用回调来禁用这个功能
    if(!user_access('administer nodes'))
    {
        $callbacks['node/add/job_post']['access callback'] = FALSE;
        // Must unset access arguments or Drupal will use user_access()
        // as a default access callback.
        // 
        unset($callbacks['node/add/job_post']['access arguments']);
    }
}
 
/**
 * Implements hook_permission().
 * 定义权限,其实drupal自己就做了这一步,这里的反而没有用处
 */
function job_post_permission()
{
    return array(
            'create job post' => array(
                    'title' => t('Create a job post'),
                    'description' => t('Create a job post') 
            ),
            'edit own job post' => array(
                    'title' => t('Edit own job post'),
                    'description' => t('Edit your own job posting') 
            ),
            'edit any job post' => array(
                    'title' => t('Edit any job post'),
                    'description' => t('Edit any job posting') 
            ),
            'delete own job post' => array(
                    'title' => t('Delete own job post'),
                    'description' => t('Delete own job posting') 
            ),
            'delete any job post' => array(
                    'title' => t('Delete any job post'),
                    'description' => t('Delete any job posting') 
            ) 
    );
}
 
/**
 * Implements hook_node_access().
 * 实现权限管理
 */
function job_node_access($op, $node, $account)
{
    // 这个够简洁
    $is_author = $account->uid == $node->uid;
    switch ($op)
    {
        case 'create' :
            // Allow if user's role has 'create joke' permission.
            // 检查是否有创建权限
            if(user_access('create job', $account))
            {
                return NODE_ACCESS_ALLOW;
            }
        case 'update' :
            // Allow if user's role has 'edit own joke' permission and user is
            // the author; or if the user's role has 'edit any joke' permission.
            if(user_access('edit own job', $account) && $is_author || user_access('edit any job', $account))
            {
                return NODE_ACCESS_ALLOW;
            }
        case 'delete' :
            // Allow if user's role has 'delete own joke' permission and user is
            // the author; or if the user's role has 'delete any joke' permission.
            if(user_access('delete own job', $account) && $is_author || user_access('delete any job', $account))
            {
                return NODE_ACCESS_ALLOW;
            }
    }
}
 
/**
 * Implement hook_form() with the standard default form.
 * 渲染页面
 */
function job_post_form($node, $form_state)
{
    return node_content_form($node, $form_state);
}
 
/**
 * Implements hook_validate().
 * 数据校验
 */
function job_post_validate($node)
{
    // Enforce a minimum character count of 2 on company names.
    // 公司名至少2个字
     
    // 测试一下und是个什么东西
//  print_r($node);
//  form_set_error('job_post_company', t('只是测试一下.'), $limit_validation_errors = NULL);
     
    if(isset($node->job_post_company) && strlen($node->job_post_company['und'][0]['value']) < 2)
    {
        form_set_error('job_post_company', t('The company name is too short. It must be atleast 2 characters.'), $limit_validation_errors = NULL);
    }
}
 
/**
 * Implements hook_insert().
 * base key才会被hook
 */
function job_post_insert($node)
{
    // log details of the job posting to watchdog
    // 在日志里记录
    watchdog('job post', 'A new job post titled: ' . $node->title . ' for company: ' . $node->job_post_company['und'][0]['value'] . ' was added by UID: ' . $node->uid, $variables = array(), WATCHDOG_NOTICE, $link = 'node/' . $node->nid);
}
 
/**
 * Implements hook_update().
 * 在修改的时候被调动
 */
function job_post_update($node)
{
    // log details of the job posting to watchdog
    watchdog('job post', 'A job post titled: ' . $node->title . ' for company: ' . $node->job_post_company['und'][0]['value'] . ' was updated by UID: ' . $node->uid, $variables = array(), WATCHDOG_NOTICE, $link = 'node/' . $node->nid);
}
 
/**
 * Implements hook_delete().
 * 只有base key相符才会hook
 */
function job_post_delete($node)
{
    // log details of the job posting to watchdog
    watchdog('job post', 'A job post titled: ' . $node->title . ' for company: ' . $node->job_post_company['und'][0]['value'] . ' was deleted by UID: ' . $node->uid, $variables = array(), WATCHDOG_NOTICE, $link = 'node/' . $node->nid);
}
 
/**
 * Implements hook_load().
 * 在构建节点对象时向对象中添加你自定义的节点属性
 */
function job_post_load($nodes)
{
    // Add a new element to the node at load time for storing the
    // job posting sponsor information
    // 
    foreach($nodes as $node)
    {
        $node->sponsor = "ACME Career Services, Your Source for Drupal Jobs";
    }
    return $node;
}
 
/**
 * Implement hook_view().
 */
function job_post_view($node, $view_mode)
{
    // Add and theme the sponsor so it appears when the job post is displayed
    // 显示新加入的赞助商字段
    if($view_mode == 'full')
    {
        $node->content['sponsor'] = array(
                '#markup' => theme('sponsor', array(
                        'sponsor' => $node->sponsor,
                        'sponsor_id' => $node->nid 
                )),
                '#weight' => 100 
        );
    }
    return $node;
}
 
/**
 * Implements hook_theme().
 * 上一个函数的#markup字段指定了使用theme函数渲染
 * 而theme函数则构成了一个job_post_theme的函数名并且调用它
 */
function job_post_theme()
{
    // define the variables and template associated with the sponsor field
    // The sponsor will contain the name of the sponsor and the sponsor_id
    // will be used to create a unique CSS ID
    return array(
            'sponsor' => array(
                    'variables' => array(
                            'sponsor' => NULL,
                            'sponsor_id' => NULL 
                    ),
                    'template' => 'sponsor'
            ) 
    );
}

sponsor.tpl.php

<?php
/**
* @file
* Default theme implementation for rendering job post sponsor information
*
* Available variables:
* - $sponsor_id: the node ID asociated with the job posting
* - $sponsor: the name of the job post sponsor
*/
?>
<div id="sponsor-<?php print $sponsor_id ?>" class="sponsor">
    <div class="sponsor-title">
        <h2>Sponsored by</h2>
    </div>
    <div class="sponsored-by-message">
This job posting was sponsored by: <?php print $sponsor; ?>
</div>
</div>

关于base键在数据库的位置:

知识共享许可协议 知识共享署名-非商业性使用-相同方式共享码农场 » Chapter 07: Working with Nodes 使用节点

评论 欢迎留言

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

我的作品

HanLP自然语言处理包《自然语言处理入门》