wikimedia/toolforge-bundle

Symfony 扩展包,提供有用的 Toolforge 功能。

安装量: 17 181

依赖: 1

建议: 0

安全: 0

星星: 13

关注者: 12

分支: 4

类型:symfony-bundle

1.7.0 2024-05-24 06:18 UTC

README

一个 Symfony 4/5 扩展包,提供 Wikimedia Toolforge 中基于网络的工具的一些常用部分。

功能

  • 针对 Meta Wiki 的 OAuth 用户身份验证。
  • 使用 Intuition 和 jQuery.i18n 库进行国际化。
  • 连接和查询 副本数据库 的接口
  • PHP 代码检查规则集
  • 基本 Wikimedia UI 样式表 (LESS)

待完成

  • 通用语言选择器 (ULS)
  • 可本地化路由
  • OOUI
  • CSSJanus
  • Addwiki
  • 将关键错误报告发送到工具维护者的电子邮件

Packagist License GitHub issues Build Status

请将所有问题报告到 GithubPhabricator(标记为 community-tech)。

目录

安装

新项目

要快速启动新项目,首先确保您已安装 ComposerSymfony CLI,然后使用 Toolforge 模板

composer create-project wikimedia/toolforge-skeleton ./my-cool-tool
cd my-cool-tool
symfony server:start -d

导航到 http://localhost:8000,您应该能看到您的新工具正在运行。

现有项目

在现有的 Symfony 项目中安装代码

composer require wikimedia/toolforge-bundle

在您的 AppKernel 中注册该扩展包

class AppKernel extends Kernel {
    public function registerBundles() {
        $bundles = [
            new Wikimedia\ToolforgeBundle\ToolforgeBundle(),
        ];
        return $bundles;
    }
}

或者 config/bundles.php

Wikimedia\ToolforgeBundle\ToolforgeBundle::class => ['dev' => true],

配置

OAuth

该扩展包创建了三个新的路由 /login/oauth_callback/logout。您的应用程序应该有一个名为 home 的路由。您需要通过在您的 config/routes.yaml 文件中添加以下内容来将这些路由注册到您的应用程序中(或等效的文件)

toolforge:
  resource: '@ToolforgeBundle/Resources/config/routes.yaml'

要配置 OAuth,首先在 Meta Wiki 上申请 OAuth 消费者,回调 URL 为 <your-base-url>/oauth_callback,并将消费者密钥和密钥添加到您的 .env 文件中。然后使用以下内容在 config/packages/toolforge.yaml 中将它们连接到您的应用程序配置中

toolforge:
  oauth:
    consumer_key: '%env(OAUTH_KEY)%'
    consumer_secret: '%env(OAUTH_SECRET)%'

如果您需要验证到不同的维基,也可以将 toolforge.oauth.url 参数设置为 Special:OAuth 的完整 URL。

在相关的 Twig 模板(通常是 base.html.twig)中添加登录链接,例如

{% if logged_in_user() %}
  {{ msg( 'toolforge-logged-in-as', [ logged_in_user().username ] ) }}
  <a href="{{ path('toolforge_logout') }}">{{ msg('toolforge-logout') }}</a>
{% else %}
  <a href="{{ path('toolforge_login') }}">{{ msg('toolforge-login') }}</a>
{% endif %}

本节下面解释了国际化的部分。OAuth 特定的部分是 logged_in_user(),这是一个扩展包提供的 Twig 函数,可以提供对当前登录用户的访问。

在开发过程中,有时您可能不想总是登录用户。要强制登录特定用户(但请注意,您仍然需要点击“登录”链接),在您的 config/packages/toolforge.yml 文件中添加 logged_in_user 键,例如

toolforge:
  oauth:
    logged_in_user: '%env(LOGGED_IN_USER)%'

在控制器中,您可以通过检查来测试用户是否已登录:

$this->get('session')->get('logged_in_user')

登录后的重定向

用户登录后,您可能希望将他们重定向回他们最初尝试查看的页面,而不是 home 路由。为此,首先确保您已注册您的 OAuth 消费者以使用 "允许消费者指定回调 URL..." 选项接受回调 URL。例如,回调的值可以是 https://my-tool.toolforge.org/oauth_callback

您的视图中的实现最好通过示例来说明。假设当前用户看到的页面显示了一个登录链接,并且您希望在用户验证后将其重定向回同一页面。您的 Twig 模板中的代码应类似于以下内容:

<a href="{{ path('toolforge_login', {'callback': url('toolforge_oauth_callback', {'redirect': app.request.uri})}) }}">Login</a>

在这里,app.request.uri 评估为用户当前查看的 URL。它作为 oauth_callback 路由的 redirect 提供的,而作为 login 路由的 callback 提供。登录链接的 URL 最终可能类似于以下内容:

https://my-tool.toolforge.org/login?callback=https%3A//my-tool.toolforge.org/oauth_callback%3Fredirect%3Dhttps%253A//my-tool.toolforge.org/my-page%253Ffoo%253Dbar

请注意,用于 redirect 值的 URL 进行了双重编码。在本例中,用户最终将被重定向回 https://my-tool.toolforge.org/my-page?foo=bar

国际化(Intuition 和 jQuery.i18n)

国际化处理方式类似于 MediaWiki 中的处理方式,翻译字符串存储在 i18n/ 目录中。该包自带一些字符串,所有这些字符串都以 toolforge_ 前缀开头;建议尽可能使用这些字符串,因为这可以减少翻译者的工作量。

1. PHP

在 PHP 中,通过以下方式在 config/packages/toolforge.yaml 中设置应用程序的 i18n '域':

toolforge:
    intuition:
        domain: 'app-name-here'

您可以通过类型提示将(该包的子类)Intuition 注入到您的控制器中,例如:

public function indexAction( Request $request, \Wikimedia\ToolforgeBundle\Service\Intuition $intuition ) { /*...*/ }

以下 Twig 函数和过滤器可用

  • msg( msg, params ) 字符串 获取单个消息。
  • bdi( text ) 字符串 使用双向隔离标签包装一个字符串。
  • msg_exists( msg ) 布尔 检查是否存在给定消息。
  • msg_if_exists( msg, params ) 字符串 如果存在消息,则获取消息,否则返回提供的字符串。
  • lang( lang ) 字符串 当前或给定语言的代码。
  • lang_name( lang ) 字符串 当前或给定语言的名字。
  • all_langs() 字符串[] i18n/ 目录中定义的所有语言的列表(代码 => 名称)。
  • is_rtl() 布尔 当前语言是否为从右到左。
  • git_tag() 字符串 当前 Git 标签,如果没有标签,则是简短哈希。
  • git_branch() 字符串 当前 Git 分支。
  • git_hash() 字符串 当前 Git 哈希。
  • git_hash_short() 字符串 当前 Git 哈希的简短版本。
  • <number>|num_format int|float 根据当前区域设置格式化数字。
  • <strings>|list_format 字符串[] 将字符串数组格式化为分隔的内联列表。在英语中,这是以逗号分隔的,并在最后一个项目之前使用 "and"。

2. Javascript

在 Javascript 中,您需要做三件事来启用国际化

  1. 将以下内容添加到您的主 JS 文件(例如 app.js)或 webpack.config.js

    require('../vendor/wikimedia/toolforge-bundle/Resources/assets/toolforge.js');
    
  2. 将以下内容添加到您的 HTML 模板(在您的 app.js 之前):

    <script type="text/javascript" src="https://tools-static.wmflabs.org/cdnjs/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    {% include '@toolforge/i18n.html.twig' %}
    

    (如果已通过其他方式加载 jQuery,则可以省略 jQuery。)

  3. 并从 public/i18n/ 链接到您的 i18n/ 目录,以便可以从 Javascript 加载语言文件。

然后您可以在任何地方使用:$.i18n( 'msg-name', paramOne, paramTwo ) 获取 i18n 消息。

副本连接管理器

如果您的工具连接到Toolforge复制的多个数据库,您可以使用ToolforgeBundle的ReplicasClient服务来确保您的应用程序打开的连接数不超过所需数量。

为了实现这一点,您首先需要将以下内容添加到您的config/packages/doctrine.yaml

doctrine.yaml
doctrine:
  dbal:
    connections:
      toolforge_s1:
        host: '%env(REPLICAS_HOST_S1)%'
        port: '%env(REPLICAS_PORT_S1)%'
        user: '%env(REPLICAS_USERNAME)%'
        password: '%env(REPLICAS_PASSWORD)%'
      toolforge_s2:
        host: '%env(REPLICAS_HOST_S2)%'
        port: '%env(REPLICAS_PORT_S2)%'
        user: '%env(REPLICAS_USERNAME)%'
        password: '%env(REPLICAS_PASSWORD)%'
      toolforge_s3:
        host: '%env(REPLICAS_HOST_S3)%'
        port: '%env(REPLICAS_PORT_S3)%'
        user: '%env(REPLICAS_USERNAME)%'
        password: '%env(REPLICAS_PASSWORD)%'
      toolforge_s4:
        host: '%env(REPLICAS_HOST_S4)%'
        port: '%env(REPLICAS_PORT_S4)%'
        user: '%env(REPLICAS_USERNAME)%'
        password: '%env(REPLICAS_PASSWORD)%'
      toolforge_s5:
        host: '%env(REPLICAS_HOST_S5)%'
        port: '%env(REPLICAS_PORT_S5)%'
        user: '%env(REPLICAS_USERNAME)%'
        password: '%env(REPLICAS_PASSWORD)%'
      toolforge_s6:
        host: '%env(REPLICAS_HOST_S6)%'
        port: '%env(REPLICAS_PORT_S6)%'
        user: '%env(REPLICAS_USERNAME)%'
        password: '%env(REPLICAS_PASSWORD)%'
      toolforge_s7:
        host: '%env(REPLICAS_HOST_S7)%'
        port: '%env(REPLICAS_PORT_S7)%'
        user: '%env(REPLICAS_USERNAME)%'
        password: '%env(REPLICAS_PASSWORD)%'
      toolforge_s8:
        host: '%env(REPLICAS_HOST_S8)%'
        port: '%env(REPLICAS_PORT_S8)%'
        user: '%env(REPLICAS_USERNAME)%'
        password: '%env(REPLICAS_PASSWORD)%'
      # If you need to work with toolsdb
      toolforge_toolsdb:
        host: '%env(TOOLSDB_HOST)%'
        port: '%env(TOOLSDB_PORT)%'
        user: '%env(TOOLSDB_USERNAME)%'
        password: '%env(TOOLSDB_PASSWORD)%'
      # If you need to work with a Trove database
      toolforge_trove:
        host: '%env(TROVE_HOST)%'
        port: '%env(TROVE_PORT)%'
        user: '%env(TROVE_USERNAME)%'
        password: '%env(TROVE_PASSWORD)%'

还需要根据需要将REPLICAS_HOST_REPLICAS_USERNAMEREPLICAS_PASSWORD和每个REPLICAS_PORT_添加到.env文件中。如果添加了新的部分(这种情况很少见),则需要相应地更新这些内容。

在生产环境中,REPLICAS_HOST_S1变量应为s1.web.db.svc.wikimedia.cloud(或用analytics替换web),每个部分类似。生产环境中的REPLICAS_PORT_变量应为3306。对于本地环境,请使用主机变量为127.0.0.1,以及任何安全的端口范围(例如,s1使用4711,s2使用4712等)。

接下来,建立到复制的SSH隧道(仅在本地环境中需要)

php bin/console toolforge:ssh

如果需要,使用--bind-address标志更改绑定地址。这可能对于Docker安装是必要的。

如果您需要针对tools-db进行操作,请传递--toolsdb标志,并确保TOOLSBD_环境变量设置正确。除非您有私有数据库,否则您应该能够使用与REPLICAS_USERNAMEREPLICAS_PASSWORD相同的用户名和密码。

如果您需要针对Trove数据库进行操作,请传递--trove标志,并确保TROVE_环境变量设置正确。这些凭证与复制品和toolsdb不同。

如果您的Toolforge UNIX shell用户名与本地不同,您需要使用--username指定它。

要查询复制,注入ReplicasClient服务,然后调用getConnection()方法,传递一个有效的数据库,您应该会得到一个Doctrine\DBAL\Connection对象。例如

# src/Controller/MyController.php
public function myMethod(ReplicasClient $client) {
    $frConnection = $client->getConnection('frwiki');
    $frUserId = $frConnection->executeQuery("SELECT user_id FROM user LIMIT 1")->fetch();
    $ruConnection = $client->getConnection('ruwiki');
    $ruUserId = $ruConnection->executeQuery("SELECT user_id FROM user LIMIT 1")->fetch();
    # ...
}

在这个例子中,$frConnection$ruConnection实际上指向同一个Connection实例,因为(在编写本文时)frwikiruwiki都位于同一部分ReplicasClient知道这样做,因为它查询(并缓存)位于https://noc.wikimedia.org的dblists。

PHP 代码检查

您可以通过向项目composer.json文件的require-dev部分添加以下内容来使用bundle的phpcs规则

"slevomat/coding-standard": "^4.8"

然后在项目的.phpcs.xml中用以下内容引用bundle的规则集

<rule ref="./vendor/wikimedia/toolforge-bundle/Resources/phpcs/ruleset.xml" />

Wikimedia UI 样式

您可能希望您的工具遵守Wikimedia设计风格指南。一个基本的LESS样式表,其中包含了一些这些设计元素,在bundle中可用。要使用它,首先安装所需的包

npm install wikimedia-ui-base less less-loader

然后导入它以及bundle的CSS文件(例如,在assets/app.less文件顶部导入)

@import '../node_modules/wikimedia-ui-base/wikimedia-ui-base.less';
@import '../vendor/wikimedia/toolforge-bundle/Resources/assets/wikimedia-base.less';

部署脚本

该bundle包含一个用于Toolforge的部署脚本,其中应用程序在Kubernetes集群上运行。

它应该添加到您的工具的crontab中,例如每十分钟运行一次

*/10 * * * * /usr/bin/jsub -once -quiet /data/project/<toolname>/<app-dir>/vendor/wikimedia/toolforge-bundle/bin/deploy.sh prod /data/project/<toolname>/<app-dir>/
  • 第一个参数是proddev,具体取决于您是想运行最高标记版本,还是最新的master分支。
  • 第二个是工具顶层目录的路径,通常是工具的主目录或其内部的一个目录(例如 /data/project/<toolname>/app)。

会话

默认情况下,Symfony 使用 / 作为会话的cookie路径,但在Toolforge上这并不安全,因为这意味着不同的工具可以访问彼此的cookie。此外,Toolforge默认可能会回退到在php.ini中定义的会话过期时间,这仅有24分钟。为了解决这个问题,请在您的 framework.yaml 中设置以下内容

framework:
  session:
    storage_id: Wikimedia\ToolforgeBundle\Service\NativeSessionStorage
    handler_id: 'session.handler.native_file'
    save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'
    cookie_lifetime: 604800 # one week

示例

此包目前在以下项目中使用

  1. 事件度量
  2. SVG翻译
  3. 全局搜索
  4. Flickr仪表板
  5. Wikisource导出
  6. Wikimedia OCR
  7. CopyPatrol
  8. Wikisource竞赛

许可

GPL 3.0或更高版本。