Jump to content
Дизайн и модификация IPS Community IPBSkinsBETA
Search In
  • More options...
Find results that contain...
Find results in...
Sign in to follow this  
siv1987

Как работают битовые опции в IPS 4

Recommended Posts

Уже целый час мучаюсь, не пойму как теперь работают битовые опции. В IPB 3 был класс IPSBWOptions с методами freeze и thaw которые конвертировали значение integer в массив с опциями, и обратно. А как сейчас с этим работать не пойму. Вижу класс \IPS\Patterns\Bitwise, вижу что автоматическая поддержка битовых полей в есть ActiveRecord, но как с ними работать без ActiveRecord? Может кто имел дело 🙂

Share this post


Link to post

Здравствуйте. Я работаю с ними. Вам что нужно сделать? Сохранение в group?

	public function get_access($g_wc3_access)
	{
		$access = [];
		$commands = \IPS\Db::i()->select( 'name, access', 'wc3_commands', ['enabled = 1 AND access != 0'] );

		foreach (iterator_to_array($commands) as $v) {
		    $access[$v['name']] = $v['access'];
		}

		$bw = new \IPS\Patterns\Bitwise( array( 'access' => ['access'] ), ['access' => $access]);
		$bw->values['access'] = $g_wc3_access;
		$bw->originalValues['access'] = $g_wc3_access;
		$bwArray = $bw->asArray();

        foreach ($bwArray as $k => $v) {
            if (!\is_string($k))
                unset($bwArray[$k]);
        }

		return ['bwArray' => $bwArray, 'access' => $access];
	}

Я написал такой вот метод для себя, всё работает.

Edited by TemKa_SD

Share this post


Link to post

Мне нужно сохранить битовое значение нескольких полей в кастомную таблицу.

@TemKa_SDнасколько я знаю из документации в конструкторе объекта Bitwise первый элемент битовое значение поле, второе маски ключей, у вас же все наоборот.
На ночь глядя так и не смог разобраться, а утром проснувшись и еще раз взглянув на документацию кажется я понял как они работают.

/* Битовая маска */
$bitOptions = array( 
	'mod_bitoptions' => array( 
		'gbw_soft_delete' => 1,
		'gbw_un_soft_delete' => 2,
		'gbw_soft_delete_see' => 4,
		'gbw_soft_delete_reason' => 8,
		'gbw_soft_delete_see_post' => 16,
		'bw_mod_soft_delete' => 32,
		'bw_mod_un_soft_delete' => 64,
		'bw_mod_soft_delete_see' => 128,
		'bw_mod_soft_delete_reason' => 256,
		'bw_mod_soft_delete_see_post' => 512,
));

/* Конструктор объекта Bitwise
 * @param	Значение из бд $row['mod_bitoptions'] 
 * @param	Битовая маска для полей $bitOptions
 */
$bitwise = new \IPS\Patterns\Bitwise( array( 'mod_bitoptions' => $row['mod_bitoptions'] ), $bitOptions );

/* Устанавливаем нужные флажки для переменных */
$bitwise['gbw_soft_delete'] = true;
$bitwise['gbw_un_soft_delete'] = true;
$bitwise['bw_mod_soft_delete_see_post'] = true;

/* Битовое значение для записи в бд */
$row['mod_bitoptions'] = $bitwise->values['mod_bitoptions'];

У вас там какая-то каша в примере если честно. Даже если предположить что в wc3_commands хранится битовая маска, то это зачем 'access' => ['access']? И это тоже $bw->values['access'] = $g_wc3_access, ведь там хранится битовое значение полей массива, а вы его сами задаете.
В общем логика странная, но спасибо за пример, он заставил меня еще раз взглянуть на документацию. 

Share this post


Link to post

@siv1987 Там у меня между масками есть пропуски, например: идет число 8, затем должно идти 16, но у меня 128 например, Bitwise автоматически заполняет, есть есть такие пропуски, так вот, я перебрал массив и вернул что мне нужно.

Share this post


Link to post

@siv1987 Смотрите, давайте обсудим мой код, тоже интересно, правильно ли я всё сделал.

1. Я собираю все ключи и маски из БД, они хранятся у меня там, так как выводятся еще в приложении C++, поэтому, нет смысла держат их в переменной IPS.

$commands = \IPS\Db::i()->select( 'name, access', 'wc3_commands', ['enabled = 1 AND access != 0'] );

https://prnt.sc/uwqdn9

2. Этот массив некорректен, его нужно преобразовать в ключ => маска:

$access = [];

foreach (iterator_to_array($commands) as $v) {
$access[$v['name']] = $v['access'];
}

https://prnt.sc/uwqekg

3. Дальше передаем собранные данные в \IPS\Patterns\Bitwise

$bw = new \IPS\Patterns\Bitwise( array( 'access' => ['access'] ), ['access' => $access]);

https://prnt.sc/uwqfn2 - здесь вот я обвел, о чем говорил выше, он создает данные с отсутствующими масками, нужно их вырезать.

https://prnt.sc/uwqgfc - здесь кстати у меня вопрос, сюда же должна залетать сумма всех масок которые нужны для проверки?

Т.е вместо кода

		$bw = new \IPS\Patterns\Bitwise( array( 'access' => ['access'] ), ['access' => $access]);
		$bw->values['access'] = $g_wc3_access;
		$bw->originalValues['access'] = $g_wc3_access;

Достаточно

$bw = new \IPS\Patterns\Bitwise( array( 'access' => $g_wc3_access ), ['access' => $access]);

Я проверил, вроде работает.

Результат: https://prnt.sc/uwqj4j

4. Далее вырезаем выше упомянутые пустые ключи:

		$bwArray = $bw->asArray();

        foreach ($bwArray as $k => $v) {
            if (!\is_string($k))
                unset($bwArray[$k]);
        }

https://prnt.sc/uwqjq0

5. Касательно этого

return ['bwArray' => $bwArray, 'access' => $access];

$bwArray - битопшионс, массив с true/false значениями доступа.

$access - нужен для формы https://prnt.sc/uwqkze https://prnt.sc/uwqlg4

------------------

https://prnt.sc/uwqlth

Share this post


Link to post

Я так понимаю массив битовых масок у вас находится в базе данных.

Метод у вас будет состоять из следующего кода:

Получаем из бд масски и создаем из него массив $bitOptions где значение поле "access" а ключ поле "name"

$bitOptions = iterator_to_array( \IPS\Db::i()->select( 'name, access', 'wc3_commands', ['enabled = 1 AND access != 0'] ) );
$bitOptions = array_column( $bitOptions, 'access', 'name' );


Создаем объект \IPS\Patterns\Bitwise, в качестве первого аргумента указываем старое int значение прежних настроек , а для второго аргумента наш массив $bitOptions
$g_wc3_access это битовое целое число всех настроек.

$access = new \IPS\Patterns\Bitwise( array( 'access' => $g_wc3_access ), ['access' => $bitOptions]);

 
Возвращаем объект

return $access;


Объект Bitwise реализует класс ArrayAccess, а значит к нему можно обращаться как к обычному массиву (для полей формы)

$access['ban'] = true;
$access['autostart'] = true;


В объекте автоматически будет вычисляться битовое значение всех его настроек которое можно получить из

 $access->values['access']

и сохранить его в базе данных.

Удалять автокомплитные поля массива наверное не нужно, они нужны для правильной работы класса, и ничем по сути не мешают.

Ну если вы генерируете форму из этих полей тогда просто их исключите при фетчинге

foreach( $access->asArray() as $k => $v )
{
	if( !is_string( $k ) )
	{
		continue;
	}
}

 

Share this post


Link to post

Спасибо

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...