Gallery: 嵌入:整合:修订间差异

来自站长百科
跳转至: 导航、​ 搜索
无编辑摘要
无编辑摘要
第7行: 第7行:


Gallery2被设计成能够轻易地被嵌入到其他应用程序中去。Embed.php中的GalleryEmbed类别
Gallery2被设计成能够轻易地被嵌入到其他应用程序中去。Embed.php中的GalleryEmbed类别
提供了API来协助G2请求的处理和对话的维持,
提供了API来协助G2请求的处理和会话的维持,
用户登入以及G2与嵌入应用程序间用户/组数据的同步。
用户登入以及G2与嵌入应用程序间用户/组数据的同步。
在此份资料中, "嵌入应用程序"简称为emApp,而Gallery2则简称为G2。
在此份资料中, "嵌入应用程序"简称为emApp,而Gallery2则简称为G2。
第63行: 第63行:


* '''入口点'''部分是关键且必要的部分。在完成该步骤之后,emApp中嵌入的G2就能运作了
* '''入口点'''部分是关键且必要的部分。在完成该步骤之后,emApp中嵌入的G2就能运作了
* '''登入及对话管理'''部分也是必要的,否则的话你就无法登入G2/以登入用户身份进行浏览
* '''登入及会话管理'''部分也是必要的,否则的话你就无法登入G2/以登入用户身份进行浏览
* '''初始用户同步''','''用户管理'''以及'''组管理'''部分仅当你想整合ruemApp的用户(及组)管理时才有必要看一看
* '''初始用户同步''','''用户管理'''以及'''组管理'''部分仅当你想整合ruemApp的用户(及组)管理时才有必要看一看
* '''可视化整合'''部分可以确保G2能够符合你对网站外观的要求并完美地整合到你的emApp中
* '''可视化整合'''部分可以确保G2能够符合你对网站外观的要求并完美地整合到你的emApp中
第71行: 第71行:


== 入口点 ==
== 入口点 ==
The first task is to create an entry point from emApp to G2 (or wrapper file). This entry point is a PHP file  which is just a small wrapper for the whole G2 application. All requests will go through this  new entry point instead of main.php (or index.php) of G2. This entry point file can be located anywhere in your website, it doesn't have to be in the G2 directory.
第一个任务就是要创建一个自emApp至G2(或封包文件)的入口点(entry point)。该入口点是一个PHP文件,也就是整个G2应用程序的小封包。所有请求都会经过此新的入口点而不是G2的main.php(或 index.php)了。该入口点文件可以位于网站的任意位置,也就是说不一定非得位于G2目录之下。


In the above directory / file listing, ''g2embed.php'' is the entry point which does all the important work (call GalleryEmbed::init(); and GalleryEmbed::handleRequest();).
在上面的目录/文件列表桌, ''g2embed.php''作为入口点承担了所有重要工作(呼叫GalleryEmbed::init();和GalleryEmbed::handleRequest();)。


For now, please see: [[Gallery:Integration_Howto#Writing_New_Integration_Code|Integration - How to write new integration code]]
现在请参看:[[Gallery:Integration_Howto#Writing_New_Integration_Code|整合-如何编写新的整合代码]]


In your GalleryEmbed::init(...); call, use 'activeUserId' => ''. Once you have done the initial user synchronization you can use your embedded G2 as normal G2 users, but before that, you can only browse as guest user.
在GalleryEmbed::init(...);呼叫中,使用'activeUserId' => ''。一旦你完成了初始用户同步,就可以以一般G2用户使用嵌入的G2了,不过在此之前,你只能以游客用户身份进行浏览。


A small code snippet to examplify the basics of GalleryEmbed is attached to this post (sample_embedding_wrapper.zip).
这里给出一段代码片段用以说明GalleryEmbed的基础,可在此帖中找到(sample_embedding_wrapper.zip)。
:*'''[http://gallery.menalto.com/files/sample_embedding_wrapper.zip sample_embedding_wrapper.zip]'''
:*'''[http://gallery.menalto.com/files/sample_embedding_wrapper.zip sample_embedding_wrapper.zip]'''




'''Warning:''' When using GalleryEmbed, you need to set the '''content-type''' of your pages yourself. Although, note that G2 currently supports only UTF8 as character encoding! Preferably before calling GalleryEmbed::handleRequest() (or init), you should call
'''警告:'''当使用GalleryEmbed时,你需要亲自设定页面的'''内容类型'''。注意G2目前只支持UTF8字符编码!一般说来,在呼叫GalleryEmbed::handleRequest() (或init)之前,你应当呼叫
   if (!headers_sent()) {
   if (!headers_sent()) {
       header('Content-Type: text/html; charset=UTF-8');
       header('Content-Type: text/html; charset=UTF-8');
第91行: 第91行:
{{expand}}
{{expand}}


== 登录及对话管理 ==
== 登录及会话管理 ==
Use the login/authentication of the emApp for G2 and keep the sessions in sync.
为G2使用emApp的登入/验证并让会话同步。


* '''If your emApp does not have a login / user management''', you can copy the G2 login form to anywhere on your website. But you need to configure the cookie path in G2 ''Site Admin'' -> ''General'' properly (it's described there).
* '''如果你的emApp 没有登入/用户管理的话''',你可以将G2登录表单复制到网站的任意位置。但你需要在G2''站点管理(Site Admin)'' -> ''General''中合理地对cookie路径进行配置才行。


* '''If your emApp has a login / user management''' (all CMS', forums, blogs, ... have something like that), you don't have to do anything special for the login. Only in the GalleryEmbed::init() call you'll have to specify what user is currently logged-in in your emApp. G2 relies on the emApp to do the authentication and just loads the corresponding user from its own backend.
* '''如果你的emApp 有登入/用户管理的话'''(所有的CMS',论坛, blogs都有类似的东西),你就无需对登入进行特殊操作了。仅在GalleryEmbed::init()呼叫中,你才需要指定emApp中当前登入的用户。G2依赖emApp进行验证,并从其自身的后端载入对应的用户。


G2 by default doesn't show the ''login'' link when embedded. You can force it to show the login link with:
默认情况下,G2在嵌入状态下不会显示''登入''链接。你可以用下面的方法强制其显示:
   $gallery->setConfig('login', true);
   $gallery->setConfig('login', true);
right after the GalleryEmbed::init(); but before the ::handleRequest(); call.
right after the GalleryEmbed::init(); but before the ::handleRequest(); call.


If your emApp has login system itself, you should at least set the 'loginRedirect' parameter in the GalleryEmbed::init(); call such that when a user clicks on login in G2, it redirects to the emApp's login page.
如果emApp自身带有登入系统的话,那么至少需要对GalleryEmbed::init();呼叫中的设定'loginRedirect'参量进行设定;这样一来,当某个用户点击G2中的登入时,就会被重定向至emApp的登入页面。


If your emApp doesn't have its own login system, it makes sense to show the login link and to not define any loginRedirect (just leave it away in your ::init(); call).
如果emApp自身不带有登入系统的话,那就有必要显示登入链接了,并且不定义任何loginRedirect(放着::init();呼叫不管就可以了)。


{{expand}}
{{expand}}
第137行: 第137行:


== 用户管理 ==
== 用户管理 ==
When using embedded G2 with an emApp that has its own user management, you should deactivate G2's user registration module since all new users should register with emApp.
当使用嵌入G2自带用户管理的emApp时,你应当禁用G2的用户注册模块,因为所有的用户都要通过emApp注册。


There are two methods to make sure that new users that are created in your emApp also get created in G2.
有两种方法能保证emApp中新建的用户也可以在G2中进行创建。
* '''Event-based synchronization''' is the preferred and recommended method. But not all emApps might support it.
* 推荐'''基于事件的同步'''方法。但并非所有的emApps都支持。
* '''On-the-fly user creation''' is the low-tech fallback solution for less powerful emApps.
* '''实时的用户创建'''是低端回退性的解决办法,主要针对较低效的emApp。


=== 基于事件的同步 ===
=== 基于事件的同步 ===
Modern CMS frameworks have an event system and allow their modules to hook your own function calls into core functionality. Usually there is an event in these CMS when a user is created, an event when a user is deleted and another when the properties of a user get updated.
现代CMS框架具有一个事件系统,并运行它们的模块将你自己的函数钩入核心功能。当某个用户被创建时,常常就是一个事件,还有用户删除以及用户属性的更新。


Your integration would then listen on such events in your emApp and call GalleryEmbed::createUser(), GalleryEmbed::deleteUser(), and GalleryEmbed::updateUser() respectively.
你的整合将在emApp中对这些事件进行侦听并分别对GalleryEmbed::createUser(),GalleryEmbed::deleteUser()和GalleryEmbed::updateUser()进行呼叫。


Since you call GalleryEmbed::createUser() right when the user gets created in emApp, G2 and your emApp will always be in sync'. This is what we call '''event-based loose coupling''' since even if the two applications are completely self-contained, manage their own data and no files need to be edited, they are kept 100% in sync.
由于在emApp中某用户创建的同时对GalleryEmbed::createUser()进行呼叫,G2和emApp将总是处于同步的。这就是所谓的'''基于事件的松耦合(event-based loose coupling)'''。因为即便两个应用程序均为完全自包含的,各自管理数据并无需要编辑的文件,它们都是100%同步的。


=== 即时用户创建 ===
=== 即时用户创建 ===
第204行: 第204行:


:'''常见问题''':
:'''常见问题''':
* What happens if a user is deleted in G2 (e.g. with GalleryEmbed::deleteUser())?
* 当在G2中删除某用户时会怎样(如使用GalleryEmbed::deleteUser())?
All items of the user get reassigned to a new owner, usually to the first admin in the admin list. The user itself is completely deleted.
该用户的所有项目都会被重新分派给某个新的所有者,通常是管理员列表中的第一个管理员。该用户自身则被完全删除。


== 站点范围配置参量 ==
== 站点范围配置参量 ==
You may want to keep site-wide configuration settings in sync with G2. E.g. such that when you change the default language in your emApp it is also changed in G2. The same applies to short URL support or the cookie path.
你可能希望将此站点范围的配置与G2保持同步,如这样的话,当修改emApp中的默认语言时,也同样作用于G2。这同样适用于段URL支持或cookie路径。


Before calling any G2 function, you must initialize G2 with:
在呼叫任何G2函数之前,你必须对G2进行初始化:
   $ret = GalleryEmbed::init(array('fullInit' => true)); // and other params if necessary
   $ret = GalleryEmbed::init(array('fullInit' => true)); // and other params if necessary
   if ($ret) {
   if ($ret) {
第218行: 第218行:


=== 默认语言 ===
=== 默认语言 ===
You can set the G2 default language with the following call:
你可以使用下面的呼叫来进行G2默认语言的设定:
   $ret = GalleryCoreApi::setPluginParameter('module', 'core', 'default.language', $g2languageCode);
   $ret = GalleryCoreApi::setPluginParameter('module', 'core', 'default.language', $g2languageCode);
       if ($ret) {
       if ($ret) {
第225行: 第225行:
       }
       }
   }
   }
But you need to convert the language code of your emApp to the G2 format before calling setPluginParameter.
但是在呼叫setPluginParameter之前,你需要将emApp的语言代码转换为G2使用的格式。


The G2 format is xx or xx_XX where xx is the ISO 2-letter language code and XX is the 2-letter country code. Use xx only if no country-specific locale is available. G2 will fall back from xx_XX to xx if no matching locale is available in your G2. if xx is not available, it will fall back to 'en_US'.
G2的格式是xx或xx_XX,这里xx是ISO 2字母语言代码,而XX是2字母国家代码。如果国家特定locale不可用的话,就仅使用xx。如果G2中没有符合的locale可用的话,G2将会由xx_XX 回退到xx。如果xx不可用,则会回退到'en_US'


=== 短URL支持 ===
=== 短URL支持 ===
You can enable short URLs for embedded G2 either as a user by browsing to your embedded G2 ''Site Admin'' section or you can do it in the code. See:
你可以浏览嵌入G2的''站点管理(Site Admin)''部分来启用短URL,或者通过代码也可以实现。参见:
* [[Gallery:URL_Rewrite#Rewrite_API_Reference|Enabling URL Rewrite for embedded G2 using the Rewrite API]]
* [[Gallery:URL_Rewrite#Rewrite_API_Reference|使用Rewirte API为嵌入的G2启用URL重写]]
* [[Gallery:Modules:rewrite#URL_Rewrite_Embedded|Setting Embedded URL Rewrite as a user]]
* [[Gallery:Modules:rewrite#URL_Rewrite_Embedded|以用户身份设定嵌入的URL重写]]


=== Cookie设定 ===
=== Cookie设定 ===
When embedded, G2 appends to all image URLs the G2 sessionId which leads to ugly URLs well, unless you look at the HTML source code, you don't see these URLs anyway). You need to set the '''cookie path''', only then G2 will stop appending the sessionId to DownloadItem URLs.
When embedded, G2在被嵌入时会向所有图片URL后置G2 sessionId,这使得URL看起来不美观。除非你查看HTML源代码,不然你是看不到这些URL的。因此你需要设定'''cookie路径''',只有这样G2才会停止将sessionId后置给DownloadItem URL。
* You can set the cookie path as a user in G2 ''Site Admin'' -> ''General''
* 你可以以用户身份在G2的''Site Admin'' -> ''General''中设定cookie路径
* Or you can set it from your code with:
* 或者你可以使用代码进行设定:
   $ret = GalleryCoreApi::setPluginParameter('module', 'core', 'cookie.path', '/');
   $ret = GalleryCoreApi::setPluginParameter('module', 'core', 'cookie.path', '/');
       if ($ret) {
       if ($ret) {
第244行: 第244行:
       }
       }
   }
   }
Please read the explanations in the site admin page on what cookie path value is correct in what case. '/' is always correct, but is not secure if you're sharing your domain with other websites in subfolders (session hijacking).
请阅读站点管理页面中有关不同情形下对应的正确cookie路径值。'/'总是正确的,但如果你与其他网站共享domain的话会不安全(“会话劫持”,session hijacking)。


=== 其他设定 ===
=== 其他设定 ===
You can set other settings too of course. Most G2 settings can be set with GalleryCoreApi::setPluginParameter().
你还可以做其他的设定。大部分的G2设定可通过GalleryCoreApi::setPluginParameter()完成。


== 单位用户/对话的语言选择 ==
== 单位用户/会话的语言选择 ==
In G2, each user can have a preferred language. Please read [[Gallery:Language_Settings|Language Settings]] to get more information about how language preferences and settings are handled in G2.
In G2, each user can have a preferred language. Please read [[Gallery:Language_Settings|Language Settings]] to get more information about how language preferences and settings are handled in G2.



2008年10月16日 (四) 14:27的版本

Gallery2的嵌入和整合

请看看有关Gallery2整合的综述。

介绍

该文档含有的整合代码的编写指导用以将G2嵌入 另一PHP应用程序中。在特定整合包中有对使用现有整合将G2嵌入另一应用程序的相关描述。在自己编写整合之前,请看一看可用整合列表。至少你可以知道需要做的及如何去做(都是开源的)。

Gallery2被设计成能够轻易地被嵌入到其他应用程序中去。Embed.php中的GalleryEmbed类别 提供了API来协助G2请求的处理和会话的维持, 用户登入以及G2与嵌入应用程序间用户/组数据的同步。 在此份资料中, "嵌入应用程序"简称为emApp,而Gallery2则简称为G2。

要求

对于emApp有某些要求,这样G2才能嵌入其中。

  • 它需为一PHP程序。在G2的XML-RPC模块尚未问世之前,你只能通过PHP与G2进行交谈。
  • emApp需要跟G2在同一服务器上
  • emApp需要使用UTF-8字符编码用作输入(请求数据)/输出(生成的HTML),并通过API与G2进行交流。如果这一点不能实现的话,就需要在与G2交流时将所有东西都转为UTF-8

注释:

  • 模块支持是一种强化的,但不是必须的:模块化整合确保你能独立地升级G2和emApp,而无需亲自费神进行大量代码的维护
  • hook/事件系统的支持是一种强化,但也不是必须的:基于事件的整合确保两个应用程序能够在不修改文件或源代码的情况下契合地很好,只要通过事件侦听器/处理器进行功能添加
  • emApp无须是数据库驱动的,但如果是这样的话,G2和emApp能够但不一定要在同一个数据库中运行
  • 你可以通过编写一个介于GalleryEmbed与应用程序间的PHP封包/接口来规避前文提到的限制(PHP,相同的服务器等),如使用remote产生与你的封包(稍后会与GalleryEmbed交谈)交谈的呼叫

综述

G2 API

G2是以面向对象的PHP(仅PHP4.x相兼容的面向对象特点)编写的。GalleryCoreApi是你与G2 API(应用程序编程接口)的主要接口。整合所用的方法将会应需要在此文档中进行说明。你最需要知道的就是GalleryCoreApi class(gallery2/modules/core/classes/GalleryCoreApi.class)以及如何处理G2状态消息(G2的错误信息管理)。

GalleryEmbed API

GalleryEmbed API是G2 API与G2嵌入特定方法的一个子集。大多数用于整合的G2方法是在GalleryEmbed类别中定义的。严格且稳定地使用GalleryEmbed方法(不要实体化GalleryEmbed对象,而应使用$ret = GalleryEmbed::functionName(); ,而不要是$embed->functionName();)!

目录结构样例

下面是G2作为模块整合在emApp中可能的目录结构样例(尤其是支持模块的CMS),但没有必要拘泥于此样例:

    |-- g2data/      
    `-- htdocs/                         (你网站的文档 / web根目录,常称为www or public_html)
        |-- index.php                   (你的emApp入口点)
        |-- modules/
        |   `-- gallery2/               (这不是G2应用程序,而仅仅是你的整合文件)
        |       |-- user/
        |       |   `-- g2embed.php     (封包文件。为emApp所呼叫,并呼叫GalleryEmbed)
        |       |-- admin/
        |       |   `-- setup.php       (可选:管理整合)
        |       |-- blocks/
        |       |   `-- image.php       (可选:G2 image block的封包)
        |       |-- hooks/      
        |       |   |-- createUser.php  (用户创建的同步)
        |       |   |-- updateUser.php  (, 用户数据更新)
        |       |   `-- deleteUser.php  (, 及删除)
        |       `-- g2helper.php        (常见辅助函数集合)
        `-- gallery2/                   (G2应用程序目录)
                |-- embed.php           (将此文件包括在封包内)
                |-- main.php            (独立G2的入口点)
                |-- modules/
                \-- ...                 (其他G2目录及文件)

后面的部分将对所有这些文件进行解释。

emApp与G2之间的关系

emApp与G2之间是一种主-仆关系(master-slave relation)而交流方式仅是simplex。这就意味着仅由emApp(主)来启动与G2(仆)之间的交流,即emApp向G2请求某些东西,接着等待返回结果。G2从来不向emApp做请求。取而代之的是,G2依赖emApp 来获知所有重要事件(用户的创建,更新以及删除等)。

阅读此文档

接下来我们在每个部分都会一步步地叙述如何先做出一个基本的整合,直到最终的功能齐全的整合方案。

  • 入口点部分是关键且必要的部分。在完成该步骤之后,emApp中嵌入的G2就能运作了
  • 登入及会话管理部分也是必要的,否则的话你就无法登入G2/以登入用户身份进行浏览
  • 初始用户同步用户管理以及组管理部分仅当你想整合ruemApp的用户(及组)管理时才有必要看一看
  • 可视化整合部分可以确保G2能够符合你对网站外观的要求并完美地整合到你的emApp中
  • 其他所有部分都是可选的,都是针对特殊需要而存在的

切记最高目标就是弄出一个无需用户手动对文件进行修改的整合。请试着按照我们有关基于事件的松耦合技巧行事,一般问题都能迎刃而解。

入口点

第一个任务就是要创建一个自emApp至G2(或封包文件)的入口点(entry point)。该入口点是一个PHP文件,也就是整个G2应用程序的小封包。所有请求都会经过此新的入口点而不是G2的main.php(或 index.php)了。该入口点文件可以位于网站的任意位置,也就是说不一定非得位于G2目录之下。

在上面的目录/文件列表桌, g2embed.php作为入口点承担了所有重要工作(呼叫GalleryEmbed::init();和GalleryEmbed::handleRequest();)。

现在请参看:整合-如何编写新的整合代码

在GalleryEmbed::init(...);呼叫中,使用'activeUserId' => 。一旦你完成了初始用户同步,就可以以一般G2用户使用嵌入的G2了,不过在此之前,你只能以游客用户身份进行浏览。

这里给出一段代码片段用以说明GalleryEmbed的基础,可在此帖中找到(sample_embedding_wrapper.zip)。


警告:当使用GalleryEmbed时,你需要亲自设定页面的内容类型。注意G2目前只支持UTF8字符编码!一般说来,在呼叫GalleryEmbed::handleRequest() (或init)之前,你应当呼叫

 if (!headers_sent()) {
     header('Content-Type: text/html; charset=UTF-8');
 }


Sections which need expansion (i.e. more detail, clarification, etc...)

登录及会话管理

为G2使用emApp的登入/验证并让会话同步。

  • 如果你的emApp 没有登入/用户管理的话,你可以将G2登录表单复制到网站的任意位置。但你需要在G2站点管理(Site Admin) -> General中合理地对cookie路径进行配置才行。
  • 如果你的emApp 有登入/用户管理的话(所有的CMS',论坛, blogs都有类似的东西),你就无需对登入进行特殊操作了。仅在GalleryEmbed::init()呼叫中,你才需要指定emApp中当前登入的用户。G2依赖emApp进行验证,并从其自身的后端载入对应的用户。

默认情况下,G2在嵌入状态下不会显示登入链接。你可以用下面的方法强制其显示:

 $gallery->setConfig('login', true);

right after the GalleryEmbed::init(); but before the ::handleRequest(); call.

如果emApp自身带有登入系统的话,那么至少需要对GalleryEmbed::init();呼叫中的设定'loginRedirect'参量进行设定;这样一来,当某个用户点击G2中的登入时,就会被重定向至emApp的登入页面。

如果emApp自身不带有登入系统的话,那就有必要显示登入链接了,并且不定义任何loginRedirect(放着::init();呼叫不管就可以了)。

Sections which need expansion (i.e. more detail, clarification, etc...)

初始用户同步

You need to map the user IDs of your emApp to the user IDs of G2. You might know other integrations that use a single database table for both applications. Integrations with G2 work a little different, we call it loose coupling or loose integration. Your emApp has its own database tables, G2 has its own tables and there's a single database table managed by G2 that maps the users from your emApp with the corresponding users in G2. You'll soon see that it has a lot of advantages.

Before you can use G2 in embedded mode as another user but guest, you need to map the users that already exist in your emApp with those that already exist in G2.

  • If both, emApp and G2 are freshly installed, there will be only maybe 1-3 default users that need to be manually mapped. Usually an admin user from emApp with the admin user of G2. Maybe also a few others. You don't need to map the guest user since you should specify activeUserId => (empty string) in your GalleryEmbed::init() call if the current request is for the guest user / non-logged-in visitor of your site. But of course you can map the guest users too, but still use activeUserId in your ::init() call for guests, else you'll get a small performance penalty.
  • If G2 and/or emApp are not freshly installed and already in use, maybe already with some registered users, you need to map all these users, hopefully in an automated way, else you have to do a lot of manual work. You should map users that exist in emApp and G2 and you should create a new user in emApp for all users in G2 that don't exist in emApp yet and the other way around.

This is a rough sketch of the algorithm that can be used to this initial mapping / import / export of users:

 Get cached lists of EmAppUsers, G2Users and Map by entityId denoted as EmAppUsers_cache, G2Users_cache and Map_by_entityId_cache respectively;
 For each g2User in G2Users_cache do
     if g2User NOT in Map_by_entityId_cache then
         Create User in EmApp with user data from g2User;
         Insert new mapping into Map;
     end if;
 end for;
 Get cached list of Map by externalId Map_by_externalId_cache;
 For each emAppUser in EmAppUsers_cache do
     if emAppUser NOT in Map_by_externalId_cache then
         Create User in G2 with user data from emAppUser;
         Insert new mapping into Map;
     else
         Update User in G2 with user data from emAppUser;
     end if;
 end for; 

In future versions of G2, we will offer a framework which will minimize the work to do the initial integration. Mike Classic wrote a G2 module which does all the logic, handles timeouts and a lot of different thing. You will just have to provide a function to get all users of your emApp, a function that creates a new user in your emApp and a function to update a user in your emApp. If you're curious how this will look like, see: http://cvs.sourceforge.net/viewcvs.py/gallery-contrib/embed/

用户管理

当使用嵌入G2自带用户管理的emApp时,你应当禁用G2的用户注册模块,因为所有的用户都要通过emApp注册。

有两种方法能保证emApp中新建的用户也可以在G2中进行创建。

  • 推荐基于事件的同步方法。但并非所有的emApps都支持。
  • 实时的用户创建是低端回退性的解决办法,主要针对较低效的emApp。

基于事件的同步

现代CMS框架具有一个事件系统,并运行它们的模块将你自己的函数钩入核心功能。当某个用户被创建时,常常就是一个事件,还有用户删除以及用户属性的更新。

你的整合将在emApp中对这些事件进行侦听并分别对GalleryEmbed::createUser(),GalleryEmbed::deleteUser()和GalleryEmbed::updateUser()进行呼叫。

由于在emApp中某用户创建的同时对GalleryEmbed::createUser()进行呼叫,G2和emApp将总是处于同步的。这就是所谓的基于事件的松耦合(event-based loose coupling)。因为即便两个应用程序均为完全自包含的,各自管理数据并无需要编辑的文件,它们都是100%同步的。

即时用户创建

If your emApp doesn't have a hook/event system, you need something else that works to make sure that all users in your emApp that access your embedded G2 also exist in G2.

If you're writing an integration for your own custom web script / application and you don't have an event system, you can of course just edit your user creation code / functions and also call GalleryEmbed::create() there (same for ::delete() and ::update()).

If you need to write an integration for a CMS / portal / ... and this integration should be easily installable and maintainable by other users for their own website, you probably can't ask them to edit / replace their emApp files just to ensure that the GalleryEmbed::create(), ... methods get called.

For such cases we recommend the on-the-fly user creation. That means that you create a user in G2 right then when you need it and not before. You don't create the user right when the user is created in your emApp, you create it in the background when the user does his first visit to the embedded G2 in your emApp.

Sample code for on-the-fly user creation (put it in your G2 wrapper file):

 $ret = GalleryEmbed::init(array('embedUri' => $embedUri, 'g2Uri' => $g2Uri, 'activeUserId' => $emAppUserId));
 if ($ret) {
     /* Error! */
     /* Did we get an error because the user doesn't exist in g2 yet? */
     $ret2 = GalleryEmbed::isExternalIdMapped($emAppUserId, 'GalleryUser');
     if ($ret2 && $ret2->getErrorCode() & ERROR_MISSING_OBJECT) {
         /* The user does not exist in G2 yet. Create in now on-the-fly */
         $ret = GalleryEmbed::createUser($emAppUserId, array('username' => $emAppUser['username'],
                                                             'language' => $emAppUser['language'], ...));
         if ($ret) {
             /* An error during user creation. Not good, print an error or do whatever is appropriate 
              * in your emApp when an error occurs */
             print "An error occurred during the on-the-fly user creation <br>";
             print $ret->getAsHtml();
             exit;
         }
     } else {
         /* The error we got wasn't due to a missing user, it was a real error */
         if ($ret2) {
             print "An error occurred while checking if a user already exists<br>";
             print $ret2->getAsHtml();
         }
         print "An error occurred while trying to initialize G2<br>";
         print $ret->getAsHtml();
         exit;
     }
 }
 /* At this point we know that either the user either existed already before or that it was just created
  * proceed with the normal request to G2 */
 $data = GalleryEmbed::handleRequest();
 /* print $data['bodyHtml'] etc.... */

But the on-the-fly user creation is problematic!

  • You only ensure that users from your emApp that access G2 enjoy a normal G2 experience
  • But you don't synchronize user deletion or user data updates (e.g. language / email / ...)
  • Also, G2 and emApp are generally out-of-sync, you're just keeping users very coarsely in sync.

If you need to use on-the-fly user creation, we recommend that you spend more time on the initial user synchronization such that you can run it from time to time or even on a regular basis / periodically and make it smarter such that it detects which users need to be updated and deleted.

Also see the somewhat outdated post at:


常见问题
  • 当在G2中删除某用户时会怎样(如使用GalleryEmbed::deleteUser())?

该用户的所有项目都会被重新分派给某个新的所有者,通常是管理员列表中的第一个管理员。该用户自身则被完全删除。

站点范围配置参量

你可能希望将此站点范围的配置与G2保持同步,如这样的话,当修改emApp中的默认语言时,也同样作用于G2。这同样适用于段URL支持或cookie路径。

在呼叫任何G2函数之前,你必须对G2进行初始化:

 $ret = GalleryEmbed::init(array('fullInit' => true)); // and other params if necessary
 if ($ret) {
     print $ret->getAsHtml();
     exit;
 }

默认语言

你可以使用下面的呼叫来进行G2默认语言的设定:

 $ret = GalleryCoreApi::setPluginParameter('module', 'core', 'default.language', $g2languageCode);
     if ($ret) {
         print $ret->getAsHtml();
         exit;
     }
 }

但是在呼叫setPluginParameter之前,你需要将emApp的语言代码转换为G2使用的格式。

G2的格式是xx或xx_XX,这里xx是ISO 2字母语言代码,而XX是2字母国家代码。如果国家特定locale不可用的话,就仅使用xx。如果G2中没有符合的locale可用的话,G2将会由xx_XX 回退到xx。如果xx不可用,则会回退到'en_US'。

短URL支持

你可以浏览嵌入G2的站点管理(Site Admin)部分来启用短URL,或者通过代码也可以实现。参见:

Cookie设定

When embedded, G2在被嵌入时会向所有图片URL后置G2 sessionId,这使得URL看起来不美观。除非你查看HTML源代码,不然你是看不到这些URL的。因此你需要设定cookie路径,只有这样G2才会停止将sessionId后置给DownloadItem URL。

  • 你可以以用户身份在G2的Site Admin -> General中设定cookie路径
  • 或者你可以使用代码进行设定:
 $ret = GalleryCoreApi::setPluginParameter('module', 'core', 'cookie.path', '/');
     if ($ret) {
         print $ret->getAsHtml();
         exit;
     }
 }

请阅读站点管理页面中有关不同情形下对应的正确cookie路径值。'/'总是正确的,但如果你与其他网站共享domain的话会不安全(“会话劫持”,session hijacking)。

其他设定

你还可以做其他的设定。大部分的G2设定可通过GalleryCoreApi::setPluginParameter()完成。

单位用户/会话的语言选择

In G2, each user can have a preferred language. Please read Language Settings to get more information about how language preferences and settings are handled in G2.

In your GalleryEmbed::init(array('g2Uri' => $g2Uri, 'embedUri' => $embedUri', 'activeUserId' => $emAppUserId, 'activeLanguage' => $langCode)); you can set the language code for the active user for the current request. See the above section to inform yourself about the xx_XX format of language codes in G2.

You don't need to set the language code on each ::init() call. If you synchronize the user preferences separately, G2 loads the correct user preferences automatically.

ImageBlocks

You can use G2's image blocks to show random images somewhere on your website. You can use it also to show the most recent images, a specific image, the most popular image, etc.

You can either use the external imageblock URL as described in G2 Site Admin -> ImageBlock or you use the GalleryEmbed::getImageBlock() method. The latter has a few advantages. E.g. the links of the imageblock point to your embedded G2 and not to your standalone G2. Also, it's faster and you can better customize it.

See:

emApp文章中的G2图片

With the GalleryEmbed::getImageBlock(); you can fetch a random image, or a random image from a specific album. But you can also fetch a specific image either by the ID number of the image or by its path. With a little logic, you can then easily e.g. use [g2:55] or similar tags in your emApp's articles to show a specific image in your articles. Joomla, Mediawiki and WordPress already have this feature in their G2 integration, other integrations follow.

可视化整合

未经修改的G2默认外观主题(matrix)可能不太衬你的emApp/网站外观。你可以通过自定义G2外观主题或选择较佳的外观主题用于嵌入,比如Siriux外观主题和WordPress外观主题等。

越来越多的整合附带有一特殊的外观主题,用以替换G2的默认外观主题,并且前者更衬emApp。

参见:外观主题指导 | 模板相关参考 | 可视化整合的相关指导

边栏

并非所有的G2外观主题都用到了边栏。但对于使用边栏的那些外观主题(如默认的matrix)来说,你可以告知G2是否要显示边栏。而如果你不想显示它的话,就可以通过变量获取边栏的HTML并将其添加到emApp的边栏。

呼叫:

 GalleryCapabilities::set('showSidebarBlocks', false);

于GalleryEmbed::init();和GalleryEmbed::handleRequest(); 呼叫之间来禁用边栏的显示。

当禁用时,你可在handleRequest 呼叫后获取边栏的HTML,通过:

 /* handlerequest呼叫 */
 $g2moddata = GalleryEmbed::handleRequest();
 /* 检查是否存在边栏内容 */
 if (!empty($g2moddata['sidebarBlocksHtml'])) {
     global $g2sidebarHtml;
     $g2sidebarHtml = $g2moddata['sidebarBlocksHtml'];
 }

在生成emApp边栏时,你可以使用$g2sidebarHtml。

高级技巧 – 基于来自G2的模板数据来生成菜单

G2不但返回基于请求的HTML以及G2模板,还会返回模板数据。有了模板数据—胜任由实时G2数据进行HTML页面的生成—你可以使用emApp的模板引擎生成菜单或其他东西。

 $g2moddata = GalleryEmbed::handleRequest();
 /* 现在你*可以*对$g2moddata['themeData']进行一些处理了 */

嵌入的外观主题vs独立外观主题

你可以指定一个不同的外观主题用于显示嵌入或独立的Gallery 注: 此方法/特点在GalleryEmbed API version 1.3中被引入。

基本方法:

  • 针对独立G2,配置你的默认外观主题(站点管理(site admin) -> 外观主题(themes))和单位相册外观主题设定(编辑相册(edit album) -> 外观主题(theme))。
  • 对嵌入模式,通过在::init()与::handleRequest()之间呼叫::setThemeForRequest($themeId)对外观主题进行覆盖。举例:
$ret = GalleryEmbed::init(...);
handleStatus($ret);
$ret = GalleryEmbed::setThemeForRequest('siriux');
handleStatus($ret);
$data = GalleryEmbed::handleRequest();


高级且灵活的技巧请见:按事件的外观主题覆盖

组管理

两个组管理系统的整合

a) 是一个不简单的任务而且
b) 个人感觉并不重要。

在你的emApp与G2直接对组进行同步可不是一个简单的任务,因为组管理的处理方式往往多种多样。用户管理常常彼此相似,但对于组管理来说,不同的应用程序所选择的方式往往不尽相同。

为何我认为组同步不重要呢?因它的收益并不明显。用户同步的优势显而易见,但是要使用组同步的话,你必须搜索大量工作所需的参数。

然而,如果你决定要做组同步的话,可以使用GalleryEmbed::createGroup();以及GalleryEmbed::addUserToGroup();等来对组和成员进行管理。它会将你emApp的组映射到G2中具有相同的用于用户的映射表的组,其中使用的思路是相同的。

G2中的组管理

G2中有3类默认组:

  • 所有人(Everybody)组:所有注册(已登录)的用户,包括所有管理员及游客(匿名)用户都在此列。
  • 已注册用户(Registered Users)组:所有注册(已登录)的用户,包括所有管理员都在此列。
  • 站点管理员(Site Admins)组:所有管理员都在该组中。

还有一些规则:

  • 请勿删除这3个默认组。
  • 请勿尝试删除游客用户以及仅有的一个管理员用户。在管理员组中必须至少存在一个用户。
  • 不违背以上规则的话,你可以随意创建/删除任意数量的组/用户。

只要在组与成员进行同步时仍应用这些规则,你就可以随心所欲地进行操作了。

搜索聚合

你可以对G2搜索引擎的结果和emApp的搜索函数进行同步。

参见:GalleryEmbed::searchScan(); | GalleryEmbed::search();

G2作为你网站的图片/多媒体存储库

你可以使用G2作为emApp的多媒体后端。此codex (MediaWiki)就是一个绝好的例子。由G2对图片进行管理而你可以在codex文章中使用G2图片。在文章编辑器中,甚至还有一个整合入的图片/相册浏览器,你可以使用鼠标在此选择来自G2的图片。

Sections which need expansion (i.e. more detail, clarification, etc...)

嵌入的图片浏览器

Having an embedded G2 is sure nice. But using it to store images for your emApp and articles, blog entries etc is even better! Some integrations already have an embedded image / album browser to pick images from your emApp article editor and use them in your new / edited articles.

  • The Gallery2 Image Chooser can be used with TinyMCE, FCKEditor, or with any web browser form.
    • Joomla!, WordPress, and Drupal all have TinyMCE and/or FCKEditor editor instances which can take advantage of the Gallery2 Image Chooser.
    • There is a live demo of how to integrate the Gallery2 Image Chooser into any browser form.
  • MediaWiki's G2 integration includes an image / album browser and advanced features for embedded images.

配置的自动化

  • 协助找到embedUri,g2Uri以及基于用户输入的embed.php路径的工具/指导
  • 有安装程序的整合

此文档对两者皆适用,单个网站的整合以及其他各种网站上用到的其他产品的整合;对于后者,有几个必要的特殊步骤可以使安装变得简单。

我们假设你在使用内容管理系统X,而由于你在将G2整合到X中,你就会想将此整合代码提供给X的所有用户,这样一来其他人就可整合他们自己的G2,而只需完成一些配置步骤就可以了。

或许你会将整合放在自己网站上供他人下载。其他网站的用户/管理员会将此代码放到他们的服务器上,并且需要对G2进行配置以兼容X。

需要配置的参量:

  • embed.php的路径。如果没有此路径,你就无法包括embed.php。
  • GalleryEmbed::init() 要求的是embedUri and g2Uri,也可以是loginRedirect等。
  • [可选] cookie路径:如果在G2中设定了cookie路径,就不会为core.DownloadItem的URL后置一个sessionId。
  • [可选] rewrite路径。如对重写模块进行了配置,就会得到更短且更加美观的URL。

还有请不要忘记初始用户/组的同步,这已在前文做过说明了。

在现有的针对xaraya,Wordpress,Joomla (mambo)的整合中,在CMS/emApp中安装G2的管理员只要输入一样东西即可,剩下的都由整合代码代劳。

管理员会被要求输入g2Uri或者说是"请将此URL/地址复制并粘贴到你的Gallery2中",如http://example.com/gallery2/。这是很体恤用户的:)

如何工作?

Include G2EmbedDiscoveryUtilities.class in your integration. You can use its

 $g2Uri = G2EmbedDiscoveryUtilities::normalizeG2Uri($g2Uri); 

to sanitize and normalize the user (administrator) input, you can then use

 list ($success, $embedPhpPath, $errorString) = G2EmbedDiscoveryUtilities::getG2EmbedPathByG2Uri($g2Uri); 

to get the absolute filesystem path of embed.php and you need to find out the embedUri yourself, shouldn't be too hard, and then run it through

 $embedUri = G2EmbedDiscoveryUtilities::normalizeEmbedUri($embedUri); 

to ensure that it is in the format that GalleryEmbed::init() expects.

The G2EmbedDiscoveryUtilities.class can be downloaded from:

An alternative is of course to restrict your integration to only work if emApp is installed in the webroot and Gallery2 in a gallery2/ folder. Then you can hardcode everything. Of course, users prefer flexibility, but they also like something that just works and a lot of them are smart enough to adjust the code to their needs. Just be sure to communicate the restrictions that you choose to make.

仍需手动/使用API来做的事

  • the rewrite API helps you to configure the rewrite module from your integration code
  • the cookie path: compare the path of the emApp with the G2 path and the longest common part should be used for the cookie path.

You can then set it with a single API call:

 $ret = GalleryCoreApi::setPluginParameter('module', 'core', 'cookie.path', $path);


Sections which need expansion (i.e. more detail, clarification, etc...)

字符集转换

If the emApp cannot be configured to work in UTF-8, character set conversion between emApp and G2 is necessary.

Convert to UTF-8 at:

  • Return value of modules/core/classes/GalleryUtilities::_internalGetRequestVariable() (you need to modify this function!)
  • Input parameters of all methods of modules/core/classes/GalleryEmbed.class (you can modify your calls to GalleryEmbed functions, no need to modify the class)

Convert from UTF-8 at:

  • Return values of all methods of modules/core/classes/GalleryEmbed.class (especially handleRequest()) (you can modify your calls to GalleryEmbed functions, no need to modify the class)

If you use other APIs (e.g. RewriteApi or GalleryCoreApi), you need to do the same conversion there as well.

如何进行转换?

For ISO-8859-1, PHP offers built-in functions:

  • $stringInUtf8 = utf8_encode($stringInIso8859_1);
  • $stringInIso8859_1 = utf8_decode($stringInUtf8);

Generally, you can use:

  • $anyEncoding = GalleryCoreApi::convertFromUtf8($stringInUtf8, $encoding);
  • $stringInUtf8 = GalleryCoreApi::convertToUtf8($anyEncoding, $encoding);
Keywords: Transliteration, Character Encoding


G2作为主(Master)的整合

The above described integration is based on the master-slave relationship with emApp as a master and G2 as the slave. emApp is supposed to to call G2 to show an embedded G2 and it's also supposed to inform G2 about all important events concerning users (create, update, delete).

An alternative scenario is if G2 is the master and should inform another application of all user registrations, logins, etc.

Since G2 has an event system itself, you can easily achieve this by creating your own G2 module which registers an event listener for GalleryEntity::save and GalleryEntity::delete events. GalleryEntity::save is called for newly created entities (users, items, ... a lot of things are entities). Your event handler needs to check the entityType for which the event was called. We are only interested in events for GalleryUser entities.


举例:

You can grab here a 'module' which does creating/updating of external users using G2 as master: http://www.site.hu/me/g2/mod_UpdateExternalUser.tar.gz (OUTDATED!)

Note: It's not an official module, neither cleaned up or finished, it's a 3rd party (beta) contribution. (Feel free to post bugs etc on forums) It was made to work with phpbb (as slave), so it needs to be adapted to any other slave environment.

Sections which need expansion (i.e. more detail, clarification, etc...)

双重整合(非主-仆关系)

An extension of the above mentioned approach (emApp as the master or G2 as the master in a master-slave simplex integration) is an integration where emApp sets in and requests things from G2 as well as the other way. That's no longer a master-slave relationship.

You simply combine the above two mentioned approaches and make sure both integrations let the other know of user registrations etc.

Warning: You will have to prevent notification loops.

Example: If a user is created in G2, G2 will call a createUser function to create a user in emApp. emApp will then want to call a createUser function to create a user in G2 since it wants to make sure everything gets synchronized. Etc. You just have to make sure that you fall into this trap and stop notifying the other application (e.g. set a global variable when creating and before calling the createUser method of the interface to the other application, check the global variable).

Sections which need expansion (i.e. more detail, clarification, etc...)