欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

模块 .info文件

编写.info文件

概述

drupal用.info文件来存储主题和模块的metadata。

对于模块来说,.info文件用于:

  • 为Drupal站点管理界面解析信息;

  • 为模块的激活和卸载提供标准和需求;

  • 提醒drupal一个模块的存在;

  • 便于一般的模块管理。

我们需要.info文件来识别模块。

示例

下面是一个.info文件的例子:

复制代码
name = Really Neat Widget
description = Provides a really neat widget for your site's sidebar.
core = 7.x
package = Views
dependencies[] = views
dependencies[] = panels
files[] = tests/example.test
configure = admin/config/content/example
复制代码

.info文件用该使用和模块一样的名称,并与模块文件一起存放在同一个文件夹内。比如,如果您的模块文件叫做example.module那么您的.info文件应该叫做example.info。

.info文件和.ini文件的格式一样,用等于号定义了不同元素的值(key=value),您也可以用引号把值括起来,引号括起来的值可以是多行的。

.info文件可以包含注释,用分号起始的行被视为注释,不会被解析。

元素

.info文件可以包含一下元素:

name(必须包含的)

  • 这是模块的显示名,将出现在模块的页面。因为这是模块要被显示的正规名字,所以我们每一个词的首字母要大写。而且要是便于用户识别的(不要包含下划线等等)。如果模块名包含了特殊的别名(css, UI, wysiwyg等)或者第三方商标(jQuery,Javascript ), 我们则遵照标准的命名。

name = Really Neat Widget

description(必须包含的)

  • 这是一个简短的最好只有一句的对模块功能的描述,它将显示在模块页面。注意,冗长的描述语言会使模块页面混乱,所以请注意言简意赅。字数被限制在255个字符。

description = Provides a really neat widget for your site's sidebar.
  • 描述可以包括超链接。下面这个例子包含了一个超链接来链接到作者的页面。当然也也可以链接到drupal.org的文档node。这比readme文件更加有用,当您要激活模块时,您可以方便的在线查看。

description = Domain manager by <a href="http://petermoulding.com">Peter Moulding .com</a>.

core(必须包含的)

  • 您模块工作的drupal版本。比如Drupal7的话就是7.x。注意模块不能细分到具体的版本号,比如6.x是正确的,而6.2则是错的。

core = 7.x

stylesheets(可选择的)

  • drupal7允许您在.info文件中添加css文件到每一个页面,和主题的.info文件功能相同。下面是一个在node模块中的.info文件例子:

stylesheets[all][] = node.css

scripts(可选择的)

  • 您可以在.info文件中添加javascript到drupal的每一页。这是集成javascript的最佳方法。而且这也是我们推荐的添加主流javascript文件的方法:

scripts[] = somescript.js

files(可选择的)

  • Drupal现在支持动态代码注册。所有的模块必须把包含类和接口声明的文件在.info文件里声明。比如:

name = Really Neat Widget
...
files[] = example.test

dependencies(可选择的)

  • 这是一个包含了您模块所需要的其他模块的数组。如果里面的模块没有出现在模块列表,您的模块是不能被激活的。如果这些模块没有被激活,系统将提示需要激活一下模块来激活本模块。

这个数组的值必须是模块文件名(以.module结尾),并全部小写,空格是不被允许的,就像下面的例子:

dependencies[] = taxonomy
dependencies[] = comment
  • 如果您想提别标记出所需模块iaode版本号,drupal夜在这个数组里提供方法。版本号不是必须添加的,除非您的模块必须需要某一版本的模块,一般是不许要添加版本号的。例子如下:

dependencies[] = modulename (major.minor)
  • 在这里major代表了主版本号,minor代表了分版本号。.x是可以代替所有的分版本号的。就像下面的例子:

name = Really Neat Widget
description = An example module
dependencies[] = exampleapi (1.x)
...
  • 在上面的例子中,example模块需要exampleapi模块来激活,版本1.0或者任何1.x的版本都可以。

dependencies[] = exampleapi (1.0)
  • 上面的例子只能允许版本你1.0的exampleapi模块来激活。

dependencies[] = exampleapi (1.x)
    • 上面的例子需要吧呢不能1.0或者任意1.x的exampleapi模块来激活。 

    • dependencies[]的元素也可以使用比较运算符:

      • =或者==代表等于

      • >大于


      • >=大于等于


      • !=不等于

dependencies[] = exampleapi (>1.0)
  • 上面的例子必须要版本号大于1.0的模块。



  • 您也可以制定核心模块的版本号:

dependencies[] = exampleapi (>7.x-1.5)
  • 上面的例子需要drupal7的任何版本,并且模块的版本号大于1.5.



  • 此外,多版本也是支持的,只需要用逗号把不同版本隔开:

dependencies[] = exampleapi (>1.0, <=3.2, !=3.0)

package(可选择的)

  • 如果您的模块与某些其他模块一同工作,或者您的模块功能与其他模块功能有较大不同,您可以在.info文件里添加一个package名。如果您不添加,那么drupal将默认将您的模块放到‘other'(“其他”)的模块列别中。一般来说我们只有在大型的模块租中才用到package名,或者这个模块对另外一组模块有一个功能的延伸, 比如Fields, Views, Commerce, Organic Groups等模块组。其他的模块我们一般都不设定package名。一般只有4个或4个以上的模块互相依赖或者有依赖关系,我们才把他们放到一个package。"Development" package是个例外,它将用于任何的编码工具模块中。



  • 在模块页面中,相同package的模块被显示在一起。所以字符应该保持一致性并遵循drupal的规则。

package = Views
  • 推荐的packge例子:

    • Administration

    • Commerce

    • Development

    • Fields

    • Media

    • User interface

    • Views

    • Voting (如果他需要VotingAPI)

模块package名大全

外部链接的图标
  • 在记录当前所有的package名,但这并不是我们推荐使用的。

php(可选择的)

  • 和drupal6一样,模块和主题可以吧他们需要的PHP版本标出 我们可以将类似于以下的例子加入到.info文件中去:

php = 5.3
  • 这里说明了模块或者主题不会在PHP5.3版本一下工作。如果模块用到了最新php版本的功能,这个元素将会很重要。如果php版本号没有被表明,那么说明该主题或模块对php的版本要求和drupal核心模块一样 。只有在模块要求的php版本号比核心模块高的时候,这个元素才需要标注。

version(不鼓励)

 

  • 这个版本号将被drupal.og生成,如果您的你模块已经建立并且被压缩封装。但是如果您的模块并不是在drupal.org的服务器上的,您可以随便用任意版本号。



  • 因为GIT中的.info文件不包含ersion,所以如果您是从git中获得的模块,您将不会有version号。如果您是用git直接获取模块,那么建议您用

git deploy

外部链接的图标
  • 模块来提供一个准确的version号。



  • 因为核心模块应用的不同的打包方法,所以版本号已经提前设定好。第三方模块不用遵循核心模块的例子。

configure(可选择的)

  • 在durpal7.x中,这代表了该模块配置页面的路径。如果这个模块被激活了,那么将会有“Configure"和Permissions"两个链接出现在模块列表页面。这就是“Configure"链接的路径。

configure = admin/config/content/example

required(可选择的)

  • 在drupal7.x中,主题和模块可以注明他们是绝对必须的,无论如何不能卸载的。用required = TRUE就可以让drupal在安装时就激活此主题或模块。一般来说,这只用于核心模块。

hidden(可选择的)

  • 在drupal7.x中,主题或模块可以注明他们是不能被显示在模块列表页面的。用hidden = TRUE就可以达到这个目的。一般用于测试的模块,当用SimpleTest测试时,一般用户不能激活该模块。

project(不鼓励,打包专用)

  • 模块的管理者不可以用这个元素。drupal.org将自动为这个元素赋值,来表明这个模块的出处。这个主要在

Update status

外部链接的图标
  • 模块中应用,这样drupal就可以检查package的版本号并提示管理员任何更新。

project status url (只能应用在自定义模块中,不能用于drupal.org的模块)

  • 这里允许管理员来提供一个URL来用Update status模块检查更新状态。在drupal.org发布的模块是不能用这个参数的。URL应该指向一个接受类似于http://my.domain.com/projects/{project}/{core}请求的RRS feed。比如:project status url应该被指向http://my.domain.com/projects

更多关于.info文件格式信息请参考 drupal_parse_info_file() documentation

外部链接的图标

 

纠错

我已经写core = 7.x,但是系统还是"This version is incompatible with the 7.x version of Drupal core",这是怎么回事?

注意dependencies[]在drupal7的格式已经变了,错误的例子:

name = Really Neat Widget
...
dependencies = foo bar   ; 5.x dependency format.
core = 6.x

正确的写法:

name = Really Neat Widget
...
; Note the [], and that each of the dependencies is on its own line:
dependencies[] = foo
dependencies[] = bar
core = 7.x

描述和口音

非英语用户注意:如果您要在description中加入非英文字母,请注意编码格式和HTML编码编译。比如此类字母“&ouml”

来自  https://www.cnblogs.com/suihui/p/3740614.html


drupal主题的.info文件

原文http://drupal.org/node/171205

译者:葛红儒 ,Think in Drupal

.info配置文件是在Drupal6中新赠的,每个主题都必须有一个.info文件.该文件应该放在你主题的目录下面.如果没有该文件的话,Drupal就找不到你的主题. .info文件的后缀名必须为".info".

  主题在Drupal内部的名字源自于这个文件.例如,如果文件名为drop.info",那么在Drupal内部,主题名字就为"drop".名字里面不要包含奇怪的字符,这是由于在Drupal中,许多PHP函数都是以主题名打头的,所以主题名和函数名存在同样的限制。起始字符必须为alphabetic字母,不能包含空格,标点等字符。可以包含下划线,但是不能包含连字符。数字字符也是允许的,但不能出现在首位。


注意:

  • 警告!模块的内部名称如果与主题的内部名称重名的话,那么你的站点将不能工作。因为可能会造成同名函数的存在,这在PHP中是非法的。每个安装了的部件(模块或者主题)都必须有一个唯一的名字。

  • .info文件中的内容是缓存在数据库中的,所以对它的修改不会在Drupal中立马生效。(不要与主题注册表的缓存相混淆了。)为了清除缓存,须这样做:


  1. 导航到"Administer > Site configuration > Performance",点击"clear"按钮。

  2. 如果启用了devel区块(安装了devel模块的话),点击"Empty cache"(“清空缓存”)链接。

  3. 然后导航到主题选择页面"Administer > Site building > Themes"

  •  

  • 语法与INIhttp://en.wikipedia.org/wiki/INI_file)文件类似。.info文件就是一个用来配置主题的的静态文本文件。文本文件的每一个行就是一个键值对(key-value),其中键位于左边,值位于右边,而中间则有一个等号。(例如:key = value)。分号是用来注释的。有些键使用了特殊的语法,带有中括号[],用来构建一列关联值,也就是我们常说的“数组”.如果你不熟悉数组的话,模仿Drupal默认.info文件中的例子,根据例子中的解释,完全可以依葫芦画瓢,得到自己的数组了。

    Drupal可以识别下面所列的键。如果.info文件没有设置的话,Drupal将为其使用默认值(http://drupal.org/node/171206)。可参看核心主题中的例子(http://drupal.org/node/171205#example#example)。

     

     

     

     

    Drupal版本:

    drupal主题的.info文件(1)

    原文: http://drupal.org/node/171205
    译者:葛红儒,Think in Drupal
    name (required)  名字(必须)
    这是用户可读的名字,与主题的Drupal内部名字可以分开单独进行设置.这在这里,字符的限制则很少.
    name = Un tema nombre de fantasia
    description (recommended)  描述(推荐)
    主题的简短描述.你可以在页面"Administer > Site building > themes"看到主题的描述.
    description = Tableless multi-column theme designed for blogs.
    screenshot 截图
    截图键时可选的,它告诉Drupal主题的缩略图在哪里,在选择主题页面(admin/build/themes)里用到了缩略图.如果.info文件中忽略了该键,那么Drupal就会使用主题目录下面的"screenshot.png"文件.
    只有当你的缩略图不叫"screenshot.png",或者你不想把它放到你主题的根目录(比如,screenshot = images/screenshot.png)下面时,才使用该键。
    screenshot = screenshot.png
     
    version (recommended) 版本(推荐)
    当发布一个新的版本时,drupal.org会自动为其添加一个版本号。当你为Drupal贡献主题时,你可以忽略该值。如果你的主题没有放到drupal.org上的话,你可以为你的主题指定任意一个版本号。
    version = 1.0
    core (required)  内核(必须)
    从Drupal 6.x开始,模块和主题的.info文件都必须指明它们兼容的Drupal内核主版本号。这里设的值将与DRUPAL_CORE_COMPATIBILITY常量相比较。如果不匹配的话,那么主题将被禁用。
    core = 6.x
    drupal.org的打包脚本,将根据每个发布版本的Drupal内核兼容性设置,自动设置该值。所以从drupal.org下载下来的主题,设置总是正确的。然而,对于直接通过CVS部署的Drupal站点来说,如果你将这一修改提交到drupal主题的.info文件中去的话,将会很有帮助。它也能够非常方便的帮用户指出,主题兼容CVS的HEAD中的哪些内核版本。
    engine (recommended) 引擎(推荐)
    主题引擎,供drupal主题使用。如果没有提供引擎的话,那么drupal主题就是独立的,比如,实现一个".theme"文件。大多数主题都使用"phptemplate"作为默认引擎。
    PHPTemplate负责查找drupal主题用到的主题函数和模板。只有当你理解你在做什么的时候,你才可以忽略这一设置。
    engine = phptemplate
     
     base theme 基主题
    子主题可以声明一个基主题。这允许主题的继承,也就是说基主题中的资源将被传递下来并在子主题中使用。drupal子主题可以声明别的子主题作为其基主题,也就是允许多重继承的存在。drupal基主题的名字为其在Drupal内部的名字。下面是Garland的子主题Minnelli的相应设置。
    base theme = garland
    更多细节可参看子主题,它们的结构和继承(http://drupal.org/node/225125)。

    regions 区域
    我们这样定义主题中的区域,声明键'regions',紧跟着“[”,接下来是内部名字,接着是“]”,然后是一个等号,右边是用户可读的区域名字。例如,regions[theRegion] = The region name.
    如果没有定义区域的话,那么使用下面的默认值。你可以根据自己的需要覆写这些值。
     
    regions[left] = Left sidebar
    regions[right] = Right sidebar
    regions[content] = Content
    regions[header] = Header
    regions[footer] = Footer
    更多细节可参看,“区块,内容和它们的区域”(http://drupal.org/node/171224)。
     
    features  特性
    许多由主题控制输出的页面元素,可以在主题的配置页面启用或者禁用. "features"键控制着出现在主题配置页面上的复选框.对于一个主题,如果你不想为其定义某个复选框时,着非常有用.为了删去某个复选框,只需要在"features"中将其删除即可.如果一个也没有定义的话,那么会输出所有默认的复选框.
    下面的例子列出了所有由features键控制的元素.通过注释掉primary_links和secondary_links元素,那么站点管理员就不会看到这两个复选框了.
    features[] = logo
    features[] = name
    features[] = slogan
    features[] = mission
    features[] = node_user_picture
    features[] = comment_user_picture
    features[] = search
    features[] = favicon
    ; These last two disabled by redefining the
    ; above defaults with only the needed features.
    ; features[] = primary_links
    ; features[] = secondary_links
    更多信息参看”定制主题设置”(http://drupal.org/node/221905).

    stylesheets 样式表
    传统方式,主题可自动的使用默认的style.css,并且可以在它们的template.php文件中通过调用drupal_add_css()来添加其它样式表。从Drupal6开始,主题也可以通过.info文件来添加样式表。
    stylesheets[all][] = theStyle.css
    更多信息可参看“样式表”一节(http://drupal.org/node/171209)。
    scripts 脚本
    传统方式,主题通过在template.php文件中调用drupal_add_js()来添加javascripts脚本。从Drupal6开始,主题也可以通过.info文件来添加javascripts了:
    scripts[] = script.js
    更多信息参看  JavaScript & jQuery一节。
    php
    这个定义了主题支持的PHP最低版本。其默认值源自DRUPAL_MINIMUM_PHP常量,它是Drupal内核所需要的php最低版本。对于一个新的版本,如果需要的话,可以对其进行重新定义。而对于大多数的主题,都不应该添加这一项。
    php = 4.3.3
     

    Drupal版本:

    Drupal核心主题中的.info文件例子

    原文: http://drupal.org/node/171205
    译者:葛红儒,Think in Drupal
    Garland:
     

     
     

    ; $Id: garland.info,v 1.5 2007/07/01 23:27:32 goba Exp $
    name = Garland
    description = Tableless, recolorable, multi-column, fluid width theme (default).
    version = VERSION
    core = 6.x
    engine = phptemplate
    stylesheets[all][] = style.css
    stylesheets[print][] = print.css

    ; Information added by drupal.org packaging script on 2008-02-13
    version = "6.0"
    project = "drupal"
    datestamp = "1202913006"
     
    Minnelli sub-theme of Garland.:
    ; $Id: minnelli.info,v 1.7 2007/12/04 20:58:44 goba Exp $
    name = Minnelli
    description = Tableless, recolorable, multi-column, fixed width theme.
    version = VERSION
    core = 6.x
    base theme = garland
    stylesheets[all][] = minnelli.css

    ; Information added by drupal.org packaging script on 2008-02-13
    version = "6.0"
    project = "drupal"
    datestamp = "1202913006"
     
    注意,从行“; Information added by drupal.org packaging script on 2008-02-13”开始直到结束,这都是由drupal.org的打包脚本自动添加的。你一定不要手工添加project(项目)和datestamp(时间戳)键。手工添加version(版本)键(第一个),那么就可以允许直接从CVS建立起来的站点使用你的主题了。
    .info文件的默认值。

    Drupal版本:

    drupal主题.info文件的默认值

     原文:http://drupal.org/node/171206

    译者:葛红儒,Think in Drupal

    下面是假定的默认值。如果它们没有被定义的话,drupal主题将自动使用这些值。

     

    注意:这些默认值是作为一个组来共同起作用的。换句话说,仅仅使用regions[sub_header] = Sub-header来覆写一个区域的话,将会造成其它默认区域的消失。为了使用它们必须对它们进行重新定义。对于"stylesheets"也是一样的。尽管从技术的角度来看,它不是一个组,定义另外一个样式表,除非你重新对"style.css"进行定义,否则是找不到它的。

     

    regions

      regions[left] = Left sidebar
      regions[right] = Right sidebar
      regions[content] = Content
      regions[header] = Header
      regions[footer] = Footer
       

    features

      features[] = logo
      features[] = name
      features[] = slogan
      features[] = mission
      features[] = node_user_picture
      features[] = comment_user_picture
      features[] = search
      features[] = favicon
      features[] = primary_links
      features[] = secondary_links
       

    stylesheets

      stylesheets[all][] = style.css
       

    scripts

      scripts[] = script.js
       

    screenshot

      screenshot = screenshot.png
       

    php (minimum support) (支持的最低版本)

    DRUPAL_MINIMUM_PHP是一个常量。它指出了运行Drupal所需php的最低版本。

      php = DRUPAL_MINIMUM_PHP

     

     来自 http://www.thinkindrupal.com/book/export/html/13


    Drupal 7 模块 .info 文件介绍

    Drupal使用.info文件来保存关于主题(theme)和模块(modules)的基本数据(metadata)。

    编码:推荐使用UTF-8,就是不带BOM(Byte Order Mark)。

    以下是一个.info的例子

    name = Really Neat Widget
    description = Provides a really neat widget for your site's sidebar.
    core = 7.x
    package = Views
    dependencies[] = views
    dependencies[] = panels
    files[] = tests/example.test
    configure = admin/config/content/example

    他包括的属性有:

    • name 必须

    • description 推荐

    • core 必须

    • stylesheets

    • scripts

    • files

    • dependencies

    • package

    • php

    • version 不鼓励

    • configure

    • required

    • hidden

    • project 不鼓励,仅适合封装时使用

    • project status url 仅用在不提交到drupal.org上的订制模块。

    解释一下:

    name (必须)

    这个将显示模块的名称,写成可读性强的,这里不要写成 really_neat_widget


    name = Really Neat Widget








    description (推荐)

    最好写一下,用一行简单说明模块用途。最多255字符

    description = Provides a really neat widget for your site's sidebar.

    说明里可以包括链接,这样可以很方便让使用者链接到指定页面,了解更多模块的信息和使用。


    description = Domain manager by <a href="http://petermoulding.com">Peter Moulding .com</a>.
    








    core (必须)

    你模板适用的Drupal版本。如果是Drupal 7就写 7.x。注意版本不能指定子版本。写7.12不正确


    core = 7.x
    








    stylesheets (可选)

    如果你每页都需要用到CSS文件,Drupal 7允许你在这里添加。格式可以参考主题(theme)里的 .info


    stylesheets[all][] = node.css
    








    scripts (可选)

    如果你每页都需要用到Javascript文件,你能在这里添加。


    scripts[] = somescript.js
    








    更多信息,可以参考 Drupal 7中Javascript的管理

    files (可选)

    Drupal 现在支持动态载入代码注册表。为了支持这个功能,所有模块必须在.info文件中事先预读那些包含类(classes)和接口(interface)声明的代码文件。

    files[] = tests/example.test
    当一个模块激活(enabled)后,Drupal将会重新扫描所有files里声明的文件,索引所有能找到的类(classes)和接口(interface)。当类第一次被访问到,它就会自动被PHP载入。

    dependencies (可选)

    运行模块时所要求其他模块支持


    dependencies[] = view
    dependencies[] = panels








    注:这里虽然只用到了模块 View 和 Panels,不过他们会用到模块Chaos tools,所以会自动加入。

    如果你要指定需要某个版本的模块,你可以用以下表达方法

    dependencies[] = modulename (major.minor)

    major是数字表达主版本号,minor可以是数字或字母表示次版本号。.x可以用来表示任何次版本号。以下例子

    dependencies[] = exampleapi (1.x)
    test_dependencies[] = autoload (>7.x-1.5)

    以上例子中,模块安装Example API主板1,任何次版本号模块(如1.0, 1.1, 1.2-beta4 etc.)

    .info文件里的dependencies[]属性还允许选择指定的版本

    • = or == 等于 (可选择:默认是等号)

    • > 大于

    • < 小于

    • >= 大等于

    • <= 小等于

    • != 不等于

    版本号大于1.0

    dependencies[] = exampleapi (>1.0)
    

    版本号要求7.x兼容,并且大于1.5

    dependencies[] = exampleapi (>7.x-1.5)

    另外还支持多版本依赖,用逗号分开

    dependencies[] = exampleapi (>1.0, <=3.2, !=3.0)

    还能用系统(system)作为模块名,来指定最小Drupal核心版本。本模块最少运行在Drupal 7.53。

    dependencies[] = system (>=7.53)
    

    package (可选)

    为模块归类,方便查找。如果不写,就会在 Others。注意这里大小写敏感,Views和views是两类。这里不应该用标点符号。

    package = Views


    php (可选)

    指定模板运行最低的PHP版本

    php = 5.3

    譬如这里就表示模块不能运行在5.3以前的版本。如果不写,就是用和Drupal相同的版本。有时用新版本PHP的一些特性,当模块需要用比核心要求更新的版本,这里才会注释。

    version (不鼓励)

    如果模块发布到drupal.org,他们会给你一个版本号字符串。如果你只是自己写的,可以写自己想要的版本号,或者不写。

    因为这里我是自己写的,没有给版本号,所以是空的。

    configure (可选)

    显示模块配置页面的的路径。当模块激活后,“配置(Configurre)”和“权限(Permission)”链接就会显示出来。这个链接就连到模块配置的概述(Overview)页面

    configure = admin/config/content/example

    点 Confirgure,就会跳转到 admin/config/content/example,配置这个模块。

    required (可选)

    如果模块绝对需要并不能被关闭,就要写:


    required = TRUE
    这些模块在Drupal安装时候就被自动激活(enabled)。这一般用Drupal的核心模块(譬如:节点(Node)、用户(User)等)








    hidden (可选)

    如果模块或者主题不可看见就设置

    hidden = TRUE

    一般这是用在测试模块

    project (不鼓励,仅适合封装时使用)

    模块维护人员不能使用这个属性。当代码上传drupal.org,他们会自动在这里分配字符串。这设置主要为了配合升级状态(Update status)模块,以致于能监控版本升级,提醒管理员有新版本可以使用。

    project status url (仅用在不提交到drupal.org上的订制模块)

    允许模块维护人员定义一个URL,让升级状态(Update status)模块来检查他们模块是否需要升级。如果模块没有在drupal.org上发布,应该在这里定义参数。URL应该指向一个XML格式,这个XML要放在 http://my.domain.com/projects/{project}/{core} ,这个例子里,


    project status url = http://my.domain.com/projects








    参考并做了修改: https://www.drupal.org/node/542202

    来自  https://blog.csdn.net/stevenhzhang/article/details/39636225


    普通分类: