Thông báo tương tác


nedka

nedka

Quản trị viên
19/09/2016 15:54

Các loại thông báo tương tác
Thông báo tương tác (notification) không chỉ được gửi dưới dạng thông báo hiện trong diễn đàn, mà còn qua thư hay Jabber, tùy vào thiết lập của người dùng.


Tạo một loại thông báo mới
Cách đặt tên loại thông báo:

Tên gói mở rộng: vinabb/demo
Tên loại thông báo: abc
Tên khai báo sau cùng: vinabb.demo.notification.type.abc
Tên khai báo này sẽ được dùng nhiều trong các đoạn mã bên dưới.

Khai báo trong config/services.yml:
Chép
services:
    vinabb.demo.notification.type.abc:
        class: vinabb\demo\notification\type\abc
        shared: false
        parent: notification.type.base
        tags:
            - { name: notification.type }
Không như các thành phần khác, thông báo có các bảng dữ liệu riêng và liên quan đến thiết lập người dùng. Vì thế, ta cần viết thêm tập tin ext.php để bật/tắt/xóa tương ứng với khi người dùng bật/tắt/xóa dữ liệu gói mở rộng, để không xảy ra xung đột. Tập tin này nằm trong thư mục gốc của gói mở rộng.
Chép
<?php

namespace vinabb\demo;

class ext extends \phpbb\extension\base
{
	// Bật thông báo cùng lúc khi gói mở rộng được cài đặt lần đầu hay bật lại
	public function enable_step($old_state)
	{
		switch ($old_state)
		{
			case '':
				// Enable notifications
				$notification = $this->container->get('notification_manager');
				$notification->enable_notifications('vinabb.demo.notification.type.abc');

				return 'notifications';
			break;

			default:
				return parent::enable_step($old_state);
			break;
		}
	}

	// Tắt thông báo cùng lúc khi gói mở rộng bị tắt
	public function disable_step($old_state)
	{
		switch ($old_state)
		{
			case '':
				// Disable notifications
				$notification = $this->container->get('notification_manager');
				$notification->disable_notifications('vinabb.demo.notification.type.abc');

				return 'notifications';
			break;

			default:
				return parent::disable_step($old_state);
			break;
		}
	}

	// Xóa hết thông báo cùng lúc dữ liệu gói mở rộng bị xóa
	public function purge_step($old_state)
	{
		switch ($old_state)
		{
			case '':
				// Purge notifications
				$notification = $this->container->get('notification_manager');
				$notification->purge_notifications('vinabb.demo.notification.type.abc');

				return 'notifications';
			break;

			default:
				return parent::purge_step($old_state);
			break;
		}
	}
}
Và cuối cùng là phần mã thực thi cho loại thông báo mới, nằm trong thư mục notification/type/:
Chép
<?php

namespace vinabb\demo\notification\type;

class abc extends \phpbb\notification\type\base
{
	// Trả về tên khai báo của loại thông báo
	public function get_type()
	{
		return 'vinabb.demo.notification.type.abc';
	}

	// Biến ngôn ngữ và nhóm xuất hiện trong bảng người dùng
	public static $notification_option = array(
		'lang' => 'NOTIFICATION_TYPE_ABC',
		'group' => 'NOTIFICATION_GROUP_MISCELLANEOUS',
	);

	// true: hiện trong bảng người dùng, false: ẩn
	public function is_available()
	{
		return true;
	}

	public static function get_item_id($data)
	{
		return date('Y', time());
	}

	public static function get_item_parent_id($data)
	{
		return 0;
	}

	// Danh sách người dùng nhận thông báo
	public function find_users_for_notification($data, $options = array())
	{
		$options = array_merge(array(
			'ignore_users'		=> array(),
		), $options);

		return $this->check_user_notification_options(array_keys($data), $options);
	}

	//
	public function users_to_query()
	{
		return array();
	}

	// Hình đại diện trong thông báo
	public function get_avatar()
	{
		$row = array(
			'avatar'		=> $this->user->data['user_avatar'],
			'avatar_type'	=> $this->user->data['user_avatar_type'],
			'avatar_width'	=> $this->user->data['user_avatar_width'],
			'avatar_height'	=> $this->user->data['user_avatar_height'],
		);

		return phpbb_get_avatar($row, 'USER_AVATAR', false, false);
	}

	// Nội dung thông báo
	public function get_title()
	{
		return $this->language->lang('NOTIFICATION_HAPPY_ANNIVERSARY',);
	}

	// Liên kết khi bấm vào thông báo
	public function get_url()
	{
		return get_username_string('profile', $this->user->data['user_id'], $this->user->data['username'], $this->user->data['user_colour']);
	}

	// Tập tin ngôn ngữ chứa nội dung thư gửi đi
	public function get_email_template()
	{
		return '@vinabb_demo/abc';
	}

	// Các biến dùng trong nội dung thư
	public function get_email_template_variables()
	{
		$data = $this->get_data('anniversary');

		return array(
			'USERNAME'	=> htmlspecialchars_decode($data[$this->user_id]['username']),
			'YEARS'		=> $data[$this->user_id]['years'],
			'U_BOARD'	=> generate_board_url(),
		);
	}

	// Lưu dữ liệu kèm thông báo
	public function create_insert_array($data, $pre_create_data = array())
	{
		$this->set_data('anniversary', $data);

		parent::create_insert_array($data, $pre_create_data);
	}
}

Khai báo
Khai báo đối tượng notification trong phương thức khởi tạo __construct() cũng như trong tập tin config/services.yml.
Chép
protected $notification;

public function __construct(\phpbb\notification\manager$notification)
{
	$this->notification= $notification;
}
Chép
        arguments:
             - '@notification_manager'
Hoặc trong phương thức main() nếu là gói chức năng:
Chép
$this->notification = $phpbb_container->get('notification_manager');

Gửi thông báo đến người dùng
Chép
$this->notification->add_notifications('vinabb.demo.notification.type.abc', $data);


Gửi thư


nedka

nedka

Quản trị viên
19/09/2016 15:54

Khai báo
Khai báo các đối tượng cần dùng trong phương thức khởi tạo __construct() cũng như trong tập tin config/services.yml.

Chép
protected $user;
protected $config;
protected $root_path;
protected $php_ext;

public function __construct(\phpbb\user $user, \phpbb\config\config $config, $root_path, $php_ext)
{
	$this->user= $user;
	$this->config = $config;
	$this->root_path= $root_path;
	$this->php_ext= $php_ext;
}
Chép
        arguments:
             - '@user'
             - '@config'
             - '%core.root_path%'
             - '%core.php_ext%'
Hoặc trong phương thức main() nếu là gói chức năng:
Chép
global $phpbb_root_path, $phpEx;

$this->user = $phpbb_container->get('user');
$this->config = $phpbb_container->get('config');
$this->root_path= $phpbb_root_path;
$this->php_ext= $phpEx;
Gửi thư
Để gửi thư, ta cần gọi thêm tập tin includes/functions_messenger.php và dùng cấu trúc mẫu như sau:
Chép
include_once($this->root_path . 'includes/functions_messenger.' . $this->php_ext);

$messenger = new \messenger(false);
$messenger->template('abc');
$messenger->to($this->user->data['user_email'], $this->user->data['username']);
$messenger->anti_abuse_headers($this->config, $this->user);
$messenger->assign_vars(array(
	'USERNAME'	=> $this->user->data['username'],
));
$messenger->send(NOTIFY_EMAIL);
Trong đó:
  • abc: là tên tập tin ngôn ngữ dùng làm nội dung thư gửi đi, nằm trong thư mục language/*/email/ của gói ngôn ngữ. Nếu bạn muốn tạo tập tin mới trong gói mở rộng của mình, ví dụ tên định danh gói mở rộng là vinabb/demo và tập tin mới là abc.txt thì khai báo là @vinabb_demo/abc . Các tập tin dùng làm nội dung thư phải có đuôi là .txt.
  • $messenger->to($this->user->data['user_email'], $this->user->data['username']): địa chỉ hộp thư và tên người nhận.
  • USERNAME: là tên biến trong nội dung thư, bạn có thể thêm vào nhiều biến nếu cần tùy biến nội dung động.
Và cuối cùng là tập tin ngôn ngữ dùng làm nội dung thư gửi đi:
Chép
Subject: Đây là thư rác dành cho bạn

Chào bạn, {USERNAME}
Bạn đã nằm trong danh sách khủng bố mỗi ngày của chúng tôi. Chúc bạn vui!

{EMAIL_SIG}
Dòng đầu tiên được dùng làm tiêu đề thư, đặt sau Subject: để phpBB nhận biết, bạn không được sửa chữ Subject: này. {EMAIL_SIG} sẽ được thay bằng chữ ký cuối thư đã thiết lập trong bảng quản trị, biến này luôn có sẵn trong mọi thư gửi đi, vì thế ta không cần khai báo lại nó, tương tự cho {SITENAME} trả về giá trị tên trang web của bạn.


Ghi nhận


nedka

nedka

Quản trị viên
19/09/2016 15:55

Khai báo
Khai báo đối tượng log trong phương thức khởi tạo __construct() cũng như trong tập tin config/services.yml.

Chép
protected $log;

public function __construct(\phpbb\log\log $log)
{
	$this->log= $log;
}
Chép
        arguments:
             - '@log'
Hoặc trong phương thức main() nếu là gói chức năng:
Chép
$this->log = $phpbb_container->get('log');

Thêm ghi nhận
Chép
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_ABC', time(), $log_data);
Trong đó, admin là loại ghi nhận quản trị, LOG_ABC là biến ngôn ngữ của ghi nhận và $log_data là mảng chứa dữ liệu ghi nhận.

Các loại ghi nhận:
  • admin: ghi nhận quản trị.
  • mod: ghi nhận điều hành.
  • user: ghi nhận người dùng.
  • critical: ghi nhận lỗi.
Trong ví dụ trên, $this->user->data['user_id'] trả về ID của người đang thực hiện thao tác. Nguyên tắc ghi nhận là ai thực hiện thì ghi lại đúng ID của người đó. Nếu bạn cần ID của người dùng khác, ví dụ ghi nhận điều hành viên A xóa bài của thành viên nào, hãy đem hết các ID của thành viên lưu vào mảng dữ liệu ghi nhận $log_data.

Tùy vào $log_data này có bao nhiêu phần tử mà ta xác định thứ tự chúng trong biến ngôn ngữ cho phù hợp. Ví dụ:
Chép
$log_data = array(
	$forum_id,
	implode(', ', $deleted_user_ids)
);
Chép
'LOG_ABC' => 'Đã xóa bài viết của các thành viên: %2$s trong chuyên mục %1$s',


Thông báo lỗi


nedka

nedka

Quản trị viên
19/09/2016 15:55

Hiện thông báo lỗi dùng giao diện người dùng

Chép
trigger_error('ERROR_ABC')
Trong đó, ERROR_ABC là biến ngôn ngữ của thông báo lỗi. Nếu biến ngôn ngữ này cần truyền thêm tham số, ta dùng:
Chép
trigger_error($this->language->lang('ERROR_ABC', $a, $b, $c))

Hiện thông báo lỗi nghiêm trọng
Chép
trigger_error('ERROR_ABC', E_USER_ERROR)


Báo cáo


nedka

nedka

Quản trị viên
19/09/2016 15:55

Khai báo
Khai báo đối tượng report (báo cáo bài viết) hoặc pm_report (báo cáo tin nhắn) trong phương thức khởi tạo __construct() cũng như trong tập tin config/services.yml.

Chép
protected $report;
protected $pm_report;

public function __construct(
	\phpbb\report\report_handler_post $report,
	\phpbb\report\report_handler_pm $pm_report
)
{
	$this->report = $report;
	$this->pm_report = $pm_report;
}
Chép
        arguments:
             - '@phpbb.report.handlers.report_handler_post'
             - '@phpbb.report.handlers.report_handler_pm'
Hoặc trong phương thức main() nếu là gói chức năng:
Chép
$this->report = $phpbb_container->get('phpbb.report.handlers.report_handler_post');
$this->pm_report = $phpbb_container->get('phpbb.report.handlers.report_handler_pm');

Gửi một báo cáo
Chép
$this->report->add_report($post_id, $reason_id, $report_text, $user_notify)
Trong đó:
  • $post_id: là số ID bài viết.
  • $reason_id: là số ID của lý do báo cáo có sẵn, gán bằng 0 sẽ chuyển vào mục "Lý do khác".
  • $report_text: là nội dung báo cáo.
  • $user_notify: bằng true sẽ thông báo cho người dùng khi báo cáo được xử lý, ngược lại là false.


Dòng lệnh


nedka

nedka

Quản trị viên
19/09/2016 15:55

Tên khai báo

Tên gói mở rộng: vinabb/demo
Tên lệnh: abc
Tên lệnh khai báo sau cùng: vinabb.demo.command.abc

Khai báo config/service.yml
Chép
services:
    vinabb.demo.command.abc:
        class: vinabb\demo\console\abc
        arguments:
            - '@language'
        tags:
            - { name: console.command }

Viết mã thực thi lệnh
Tạo tập tin console/abc.php với cấu trúc mã như sau:
Chép
<?php

namespace vinabb\demo\console;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;

class abc extends Command
{
	protected $language;
	
	public function __construct(
		\phpbb\language\language $language
	)
	{
		$this->language = $language;
		parent::__construct();
	}

	// Khai báo tên lệnh, thêm tập tin ngôn ngữ...
	protected function configure()
	{
		$this->language->add_lang('cli', 'vinabb/demo');
		$this->setName('abc')
			->setDescription($this->language->lang('CLI_DESCRIPTION_ABC'));
	}

	// Phần mã thực thi
	protected function execute(InputInterface $input, OutputInterface $output)
	{
		// Mã thực thi viết tại đây...

		// Thông báo sau khi chạy xong
		$output->writeln($this->language->lang('CLI_DONE_ABC'));
	}

	// Phần tương tác đầu khi gõ lệnh
	protected function interact(InputInterface $input, OutputInterface $output)
	{
		$helper = $this->getHelper('question');
		$question = new Question($this->language->lang('CLI_QUESTION_ABC'));
		$your_name = $helper->ask($input, $output, $question);
		$output->writeln($this->language->lang('CLI_ANSWER_ABC', $your_name));
	}
}
Và đừng quên tập tin ngôn ngữ language/*/cli.php đi kèm lệnh này nhé:
Chép
<?php

if (!defined('IN_PHPBB'))
{
	exit;
}

if (empty($lang) || !is_array($lang))
{
	$lang = array();
}

$lang = array_merge($lang, array(
	'CLI_DESCRIPTION_ABC' => 'Chỉ muốn biết bạn tên gì',
	'CLI_QUESTION_ABC' => 'Bé tên gì: ',
	'CLI_ANSWER_ABC' => 'Mấy bé tên %s thông minh lém...',
	'CLI_DONE_ABC' => 'Hỏi cung xong rồi!',
));

Chạy thử lệnh
Trong ví dụ trên, phương thức interact() sẽ chạy đầu tiên khi ta gõ lệnh để thu thập dữ liệu nhập từ người quản trị, sau đó mới tới phương thức execute() chứa mã thực thi chính chạy và thông báo thành công.

Ta chạy thử dòng lệnh vừa tạo ở trên qua cú pháp:
Chép
php bin/phpbbcli.php abc
Chép
> php bin/phpbbcli.php abc
> Bé tên gì: 
Nhập từ bàn phím phpBB và bấm Enter.
Chép
> php bin/phpbbcli.php abc
> Bé tên gì: phpBB
> Mấy bé tên phpBB thông minh lém...
> Hỏi cung xong rồi!


Mã xác nhận


nedka

nedka

Quản trị viên
19/09/2016 15:55

Khai báo
Khai báo đối tượng captcha trong phương thức khởi tạo __construct() cũng như trong tập tin config/services.yml.

Chép
protected $captcha;

public function __construct(\phpbb\captcha\factory $captcha)
{
	$this->captcha= $captcha;
}
Chép
        arguments:
             - '@captcha.factory'
Hoặc trong phương thức main() nếu là gói chức năng:
Chép
$this->captcha= $phpbb_container->get('captcha.factory');

Sử dụng
Khởi động mã xác nhận:
Chép
if ($this->config['enable_confirm'])
{
	$this->captcha->get_instance($this->config['captcha_plugin']);
	$this->captcha->init(99);
}
Giá trị 99 ở trên có mục đích gì? Bởi vì bộ nhân phpBB đã sử dụng 4 giá trị đầu (từ 1 đến 4) cho 4 chức năng sau:
  • Đăng ký: Có hằng là CONFIRM_REG mang giá trị 1.
  • Đăng nhập sai: Có hằng là CONFIRM_LOGIN mang giá trị 2.
  • Khách gửi bài: Có hằng là CONFIRM_POST mang giá trị 3.
  • Khách báo cáo: Có hằng là CONFIRM_REPORT mang giá trị 4.
nên ta chỉ cần dùng một giá trị nào khác chúng là được, tránh xung đột chức năng.

Kiểm tra người dùng nhập đúng mã chưa:
Chép
if ($this->config['enable_confirm'] && !$this->captcha->is_solved())
{
	$vc_response = $this->captcha->validate($data);

	if ($vc_response !== false)
	{
		// $vc_response lúc này chứa thông báo lỗi lý do nhập sai
	}

	if ($this->config['max_reg_attempts'] && $this->captcha->get_attempt_count() > $this->config['max_reg_attempts'])
	{
		// Người dùng nhập sai quá số lần đã thiết lập
	}
}
Nếu trang này thường xuyên yêu cầu nhập mã, nếu cần, bạn có thể tha cho thành viên những lần nhập sai trước sau khi hoàn tất xử lý:
Chép
if ($this->config['enable_confirm']
{
	$this->captcha->reset();
}
Xuất một biến giao diện để hiển thị hình ảnh mã xác nhận:
Chép
if ($this->config['enable_confirm'])
{
	$this->template->assign_vars(array(
		'CAPTCHA_TEMPLATE' => $this->captcha->get_template(),
	));
}
Và cuối cùng, thêm hình ảnh này vào tập tin giao diện HTML:
Chép
{% if CAPTCHA_TEMPLATE %}
	{% include CAPTCHA_TEMPLATE %}
{% endif %}


Thao tác hẹn giờ


nedka

nedka

Quản trị viên
19/09/2016 15:56

...


Các hàm thường dùng


nedka

nedka

Quản trị viên
19/09/2016 15:56

Hiện tên người dùng kèm màu chữ và liên kết đến trang cá nhân

Chép
get_username_string('full', $this->user->data['user_id'], $this->user->data['username'], $this->user->data['user_colour'])

Hiện hình đại diện
Chép
phpbb_get_avatar($this->user->data)

Yêu cầu đăng nhập
Chép
login_box()

Chuyển trang
Chuyển trang nội bộ (cùng hệ thống phpBB):
Chép
redirect(đường_dẫn)
Chuyến trang khác không phải phpBB hoặc tên miền khác:
Chép
redirect(liên_kết, false, true)

Lấy địa chỉ truy cập hệ thống
Chép
generate_board_url()


Trả về danh sách lựa chọn
Chọn ngôn ngữ:
Chép
language_select('giá_trị_mặc_định_chọn_sẵn')
Chọn giao diện:
Chép
style_select('giá_trị_mặc_định_chọn_sẵn')
Chọn múi giờ:
Chép
phpbb_timezone_select($this->template, $this->user, 'giá_trị_mặc_định_chọn_sẵn')


Quan điểm

  • Không đề cập chính trị, tôn giáo, nội dung đồi trụy.
  • Giữ gìn sự trong sáng của Tiếng Việt.
  • Không chia sẻ phần mềm vi phạm bản quyền.
  • Không rao vặt và không nhận đặt quảng cáo.
  • Dù trong túi hết tiền thì diễn đàn phpBB của anh cũng phải ngay ngắn.

Chuyện tình VinaBB

17/07/2004: Yêu phpBB từ phiên bản 2.0.10.
22/10/2006: Cất tiếng cười chào đời.
11/06/2007: Chính thức định cư trên Olympus, Sao Hỏa.
11/06/2009: Mất liên lạc với Trái Đất. [ Phiên bản 2007 ]
28/07/2016: Trôi dạt đến mặt trăng Rhea, Sao Thổ.
12/12/2016: Cuộc hành trình mới lại bắt đầu…

Code in Viet Nam

Cống hiến hết mình vì Tổ Quốc Việt Nam Xã Hội Chủ Nghĩa

Quản trị viên

nedka

VinaBB

NEDKA Solutions

Đơn vị chủ quản

Chúng tôi chịu trách nhiệm toàn bộ nội dung có trên VinaBB.vn trước pháp luật.