public function quote($db_string, $db_values, $connection = null) { // Only bother if there's something to replace. if (strpos($db_string, '{') !== false) { // This is needed by the callback function. $this->_db_callback_values = $db_values; if ($connection === null) { $this->_db_callback_connection = $this->_connection; } else { $this->_db_callback_connection = $connection; }
I was thinking to change part of it (as below) but it causes long loop and thus, page error 500:
Title: Re: Looking for Correct Changes
Post by: ahrasis on November 04, 2016, 01:01:06 am
I think it is better for me to list the code we changed for database files in 1.0 so that the equivalent in 1.1 may be seen and advised as a whole.
Currently the addon do work without the changes but the said changes are needed for limiting the displayed boards, topics and posts.
I will be out Friday prayer and will post them all after that.
Title: Re: Looking for Correct Changes
Post by: emanuele on November 05, 2016, 09:35:36 am
I'm pretty sure you will not like the answer I'm going to give you, but that's how I would try to do it (provided I didn't test the code so tit may not work as expected...).
Two new files, one called Db-mysqlm.class.php, while the other Db-postgresql.class.php in /sources/database/ The two containing a slightly modified version of the database class, for example, for the mysql one:
// Let's define the name of the class so that we will be able to use it in the instantiations if (!defined('DB_TYPE')) define('DB_TYPE', 'MySQLm');
/** * SQL database class, implements database class to control mysql functions */ class Database_MySQLm extends Database_MySQL { protected static $_string = '';
public static function initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_options = array()) { // Initialize the instance... if not done already! if (self::$_db === null) self::$_db = new self();
return $return; } public function replacement__callback($matches) { global $user_info, $db_prefix, $modSettings;
// Connection gone??? This should *never* happen at this point, yet it does :'( if (!$this->validConnection($this->_db_callback_connection)) Errors::instance()->display_db_error();
// if in subforum add find_in_set(id_board or id_cat) if ($matches[1] === 'query_see_board') { preg_match('/([a-zA-Z\.]+(id_cat|id_board)).?/is', $this->_string, $cols); if(!empty($modSettings['subforums'][$_SERVER['SERVER_NAME']]) && isset($cols[2])) return $user_info['query_see_board'] .' AND FIND_IN_SET('. $cols[1] .', \''. ($cols[2] == 'id_cat' ? $modSettings['subforums'][$_SERVER['SERVER_NAME']]['cats'] : $modSettings['subforums'][$_SERVER['SERVER_NAME']]['boards']) .'\') != 0'; else return $user_info['query_see_board']; }
// if in subforum add find_in_set(id_board or id_cat) if ($matches[1] === 'query_wanna_see_board') { preg_match('/([a-zA-Z\.]+(id_cat|id_board)).?/is', $this->_string, $cols); if(!empty($modSettings['subforums'][$_SERVER['SERVER_NAME']]) && isset($cols[2])) return $user_info['query_wanna_see_board'] .' AND FIND_IN_SET('. $cols[1] .', \''. ($cols[2] == 'id_cat' ? $modSettings['subforums'][$_SERVER['SERVER_NAME']]['cats'] : $modSettings['subforums'][$_SERVER['SERVER_NAME']]['boards']) .'\') != 0'; else return $user_info['query_wanna_see_board']; }
// special tag.. add find_in_set(...) if ($matches[1] === 'subforums_see_board') { if(!empty($modSettings['subforums'][$_SERVER['SERVER_NAME']]) && isset($matches[2])) return ' AND FIND_IN_SET('. str_replace('-', '.', $matches[2]) .', \''. $modSettings['subforums'][$_SERVER['SERVER_NAME']]['boards'] .'\') != 0'; else return ''; }
// Installing $settingsForm = new Settings_Form(Settings_Form::FILE_ADAPTER); $settingsForm->setConfigValues(array('db_type' => 'MySQLm'); $settingsForm->save();
// Uninstalling $settingsForm = new Settings_Form(Settings_Form::FILE_ADAPTER); $settingsForm->setConfigValues(array('db_type' => 'MySQL'); $settingsForm->save();
Later I'll see what can be done about you "classic" way. Most likely it will not differ much, just change the replacement__callback method accept two arguments?
Title: Re: Looking for Correct Changes
Post by: ahrasis on November 05, 2016, 09:56:17 pm
Actually, I love it because it extends the original file with other file rather than modifying it. Currently in 1.0 branch, we modify as follows:
<file name="SOURCEDIR/database/Db-mysql.class.php"> <operation> <search position="replace"><![CDATA[ public static function initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_options = array()) { global $mysql_set_mode;
]]></search> <add><![CDATA[ public static function initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_options = array()) { global $mysql_set_mode;
// include SubForums DB functions include_once(ADMINDIR .'/SubForums/Subforums-DB.php'); ]]></add> </operation>
<operation> <search position="replace"><![CDATA[ public function replacement__callback($matches) { global $db_callback, $user_info, $db_prefix;
list ($values, $connection) = $db_callback;
// Connection gone??? This should *never* happen at this point, yet it does :'( if (!is_object($connection)) display_db_error();
if ($matches[1] === 'db_prefix') return $db_prefix;
if ($matches[1] === 'query_see_board') return $user_info['query_see_board'];
if ($matches[1] === 'query_wanna_see_board') return $user_info['query_wanna_see_board']; ]]></search> <add><![CDATA[ public function replacement__callback($matches) { global $db_callback, $user_info, $db_prefix;
list ($query, $values, $connection) = $db_callback;
<operation> <search position="replace"><![CDATA[ // Only bother if there's something to replace. if (strpos($db_string, '{') !== false) { // This is needed by the callback function. $db_callback = array($db_values, $connection === null ? $this->_connection : $connection); ]]></search> <add><![CDATA[ // Only bother if there's something to replace. if (strpos($db_string, '{') !== false) { // This is needed by the callback function. $db_callback = array($db_string, $db_values, $connection === null ? $this->_connection : $connection); ]]></add> </operation>
<operation> <search position="replace"><![CDATA[ if (empty($db_values['security_override']) && (!empty($db_values) || strpos($db_string, '{db_prefix}') !== false)) { // Pass some values to the global space for use in the callback function. $db_callback = array($db_values, $connection); ]]></search> <add><![CDATA[ if (empty($db_values['security_override']) && (!empty($db_values) || strpos($db_string, '{db_prefix}') !== false)) { // Pass some values to the global space for use in the callback function. $db_callback = array($db_string, $db_values, $connection); ]]></add> </operation> </file>
<file name="SOURCEDIR/database/Db-postgresql.class.php"> <operation> <search position="replace"><![CDATA[ public static function initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_options = array()) { ]]></search> <add><![CDATA[ public static function initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_options = array()) {
<operation> <search position="replace"><![CDATA[ public function replacement__callback($matches) { global $db_callback, $user_info, $db_prefix;
list ($values, $connection) = $db_callback;
// Connection gone? if (!is_resource($connection)) display_db_error();
if ($matches[1] === 'db_prefix') return $db_prefix;
if ($matches[1] === 'query_see_board') return $user_info['query_see_board'];
if ($matches[1] === 'query_wanna_see_board') return $user_info['query_wanna_see_board']; ]]></search> <add><![CDATA[ public function replacement__callback($matches) { global $db_callback, $user_info, $db_prefix;
list ($query, $values, $connection) = $db_callback;
<operation> <search position="replace"><![CDATA[ // Only bother if there's something to replace. if (strpos($db_string, '{') !== false) { // This is needed by the callback function. $db_callback = array($db_values, $connection === null ? $this->_connection : $connection); ]]></search> <add><![CDATA[ // Only bother if there's something to replace. if (strpos($db_string, '{') !== false) { // This is needed by the callback function. $db_callback = array($db_string, $db_values, $connection === null ? $this->_connection : $connection); ]]></add> </operation>
<operation> <search position="replace"><![CDATA[ if (empty($db_values['security_override']) && (!empty($db_values) || strpos($db_string, '{db_prefix}') !== false)) { // Pass some values to the global space for use in the callback function. $db_callback = array($db_values, $connection); ]]></search> <add><![CDATA[ if (empty($db_values['security_override']) && (!empty($db_values) || strpos($db_string, '{db_prefix}') !== false)) { // Pass some values to the global space for use in the callback function. $db_callback = array($db_string, $db_values, $connection); ]]></add> </operation> </file>
I will test this first, soonest.
Questions: 1. Can most of core files be extended and overwritten like that? 2. Can I used that similar method instead of using manual modification (currently being used)?
Title: Re: Looking for Correct Changes
Post by: emanuele on November 06, 2016, 03:43:33 am
Quote from: ahrasis – Actually, I love it because it extends the original file with other file rather than modifying it.
Glad you like it, I thought you wouldn't be much happy because is a bit more complex here and there. :)
Of course, all classes can be extended. That said, in the current state of 1.0 and partially 1.1, only a part of the code can be expanded this way, and anyway, the trick I used above is kind of tricky because if another addon has to change the class it would break your code. I suggested it because as far as I know, yours is the only case that require to change the database functions and as such it is acceptable, but remember it may not always work. In the future, it would probably be wise to take in consideration this kind of features as well.
Quote from: ahrasis – 2. Can I used that similar method instead of using manual modification (currently being used)?
In 1.0 is slightly trickier I think, I'm not sure I would recommend it.
Title: Re: Looking for Correct Changes
Post by: ahrasis on November 07, 2016, 11:45:32 am
// Installing $settingsForm = new Settings_Form(Settings_Form::FILE_ADAPTER); $settingsForm->setConfigValues(array('db_type' => 'MySQLm'); $settingsForm->save();
// Uninstalling $settingsForm = new Settings_Form(Settings_Form::FILE_ADAPTER); $settingsForm->setConfigValues(array('db_type' => 'MySQL'); $settingsForm->save();
How do I run this code at install and uninstall again? Thank you.
Title: Re: Looking for Correct Changes
Post by: emanuele on November 07, 2016, 11:52:47 am
IIRC you have an install.php and an uninstall.php in he package, or not? Just add it to them (the first part to install.php and the second to uninstall.php, obviously).
$settingsForm = new Settings_Form(Settings_Form::FILE_ADAPTER); $settingsForm->setConfigValues(array('db_type' => 'MySQLm'); $settingsForm->save();
?>
It causes temporary 500 error after I click install (action=admin;area=packages;sa=install2;package=MultiTenancy11.b305.elkarte.ahrasis.com.zip;pid=0) and when refresh, the page comes back with this warning:
QuoteAn Error Has Occurred Your session timed out while posting. Please go back and try again.
The installation did work without that install.php.
Title: Re: Looking for Correct Changes
Post by: emanuele on November 07, 2016, 02:04:36 pm
<file name="SOURCEDIR/database/Db-mysql.class.php"> <operation> <search position="replace"><![CDATA[ public static function initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_options = array()) { global $mysql_set_mode;
]]></search> <add><![CDATA[ public static function initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_options = array()) { global $mysql_set_mode;
// include SubForums DB functions include_once(ADMINDIR .'/SubForums/Subforums-DB.php'); ]]></add> </operation>
<operation> <search position="replace"><![CDATA[ public function replacement__callback($matches) { global $db_callback, $user_info, $db_prefix;
list ($values, $connection) = $db_callback;
// Connection gone??? This should *never* happen at this point, yet it does :'( if (!is_object($connection)) display_db_error();
if ($matches[1] === 'db_prefix') return $db_prefix;
if ($matches[1] === 'query_see_board') return $user_info['query_see_board'];
if ($matches[1] === 'query_wanna_see_board') return $user_info['query_wanna_see_board']; ]]></search> <add><![CDATA[ public function replacement__callback($matches) { global $db_callback, $user_info, $db_prefix;
list ($query, $values, $connection) = $db_callback;
<operation> <search position="replace"><![CDATA[ // Only bother if there's something to replace. if (strpos($db_string, '{') !== false) { // This is needed by the callback function. $db_callback = array($db_values, $connection === null ? $this->_connection : $connection); ]]></search> <add><![CDATA[ // Only bother if there's something to replace. if (strpos($db_string, '{') !== false) { // This is needed by the callback function. $db_callback = array($db_string, $db_values, $connection === null ? $this->_connection : $connection); ]]></add> </operation>
<operation> <search position="replace"><![CDATA[ if (empty($db_values['security_override']) && (!empty($db_values) || strpos($db_string, '{db_prefix}') !== false)) { // Pass some values to the global space for use in the callback function. $db_callback = array($db_values, $connection); ]]></search> <add><![CDATA[ if (empty($db_values['security_override']) && (!empty($db_values) || strpos($db_string, '{db_prefix}') !== false)) { // Pass some values to the global space for use in the callback function. $db_callback = array($db_string, $db_values, $connection); ]]></add> </operation> </file>
<file name="SOURCEDIR/database/Db-postgresql.class.php"> <operation> <search position="replace"><![CDATA[ public static function initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_options = array()) { ]]></search> <add><![CDATA[ public static function initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, $db_options = array()) {
<operation> <search position="replace"><![CDATA[ public function replacement__callback($matches) { global $db_callback, $user_info, $db_prefix;
list ($values, $connection) = $db_callback;
// Connection gone? if (!is_resource($connection)) display_db_error();
if ($matches[1] === 'db_prefix') return $db_prefix;
if ($matches[1] === 'query_see_board') return $user_info['query_see_board'];
if ($matches[1] === 'query_wanna_see_board') return $user_info['query_wanna_see_board']; ]]></search> <add><![CDATA[ public function replacement__callback($matches) { global $db_callback, $user_info, $db_prefix;
list ($query, $values, $connection) = $db_callback;
<operation> <search position="replace"><![CDATA[ // Only bother if there's something to replace. if (strpos($db_string, '{') !== false) { // This is needed by the callback function. $db_callback = array($db_values, $connection === null ? $this->_connection : $connection); ]]></search> <add><![CDATA[ // Only bother if there's something to replace. if (strpos($db_string, '{') !== false) { // This is needed by the callback function. $db_callback = array($db_string, $db_values, $connection === null ? $this->_connection : $connection); ]]></add> </operation>
<operation> <search position="replace"><![CDATA[ if (empty($db_values['security_override']) && (!empty($db_values) || strpos($db_string, '{db_prefix}') !== false)) { // Pass some values to the global space for use in the callback function. $db_callback = array($db_values, $connection); ]]></search> <add><![CDATA[ if (empty($db_values['security_override']) && (!empty($db_values) || strpos($db_string, '{db_prefix}') !== false)) { // Pass some values to the global space for use in the callback function. $db_callback = array($db_string, $db_values, $connection); ]]></add> </operation> </file>
Title: Re: Looking for Correct Changes
Post by: emanuele on November 09, 2016, 02:55:03 am
If I got it right you basically need $db_string in the replacement__callback. If so, add to the abstract class a new property (similarly to what I did above, but editing the abstract Database_Abstract class file), then, in query and quote (similarly to what I did above) you assign the string to this new property[1].
to the Database_Abstract. Then, in each of the database classes (either the abstract of the dbms-specific depending where the methods exist), in quote and query, you'll add before the call of replacement__callback something like:
1 Property is the name of variables when are "part" of a class, so the $this->something, the "something" is a property. Instead, if it is a function, it's called a method.↵
Title: Re: Looking for Correct Changes
Post by: ahrasis on November 27, 2016, 04:02:24 am
I have to note this as unfinished so that I won't forget to get it working when I have free time.