I am posting related topics mod (original license is under BSD-New) but I am facing some problems. During after I click install, I come to extracting page with this database error:
Table 'elk3.elkarte_related_topics' doesn't exist
File: D:\UniServerZ\www\3\sources\database\DbTable-mysql.php
Line: 548
Note: Your database version is 1.0.2.
SHOW FIELDS
FROM [icode]elkarte_related_topics[/icode]
Attached is the ported package.
Sounds like a potential bug: based on just the error I'd say the code is checking to see if some column exists, but the table itself is not there and it fails.
Will check later.
Hurmmm... Could this be caused by wrongly used $db and $dbtbl? Maybe I recheck this too later.
Found one of it. I wrote $dbtbl->db_table_structure instead of $db->db_table_structure .
But now, I only got a blank page. Lol.
hmm... I guess you wrote $db->db_table_structure instead of $dbtbl->db_table_structure ;)
Anyway there is also a
$dbtbl->db_table_structure('{db_prefix}' . $table_name, $table['columns'], $table['indexes']);
that should likely be
$dbtbl->db_create_table(...);
the one in the
if (!$tableExists && empty($table['elk']))
condition.
Anyway, what I would do is:
* remove
$tableExists = in_array($db_prefix . $table_name, $existingTables);
then, instead of
if (!$tableExists && empty($table['elk']))
$dbtbl->db_table_structure('{db_prefix}' . $table_name, $table['columns'], $table['indexes']);
// Update table
else
use
$tableExists = $dbtbl->db_create_table(...);
if ($tableExists === false)
Thank you very much
@emanuele . Finally, it is installable but now stuck in two more items i.e. "settings" and "methods".
Here is the settings function which shows the settings page but cannot be properly saved. Hope some one can point its misake(s). ;)
function RelatedTopicsAdminSettings($return_config = false)
{
global $txt, $context, $scripturl, $modSettings;
loadlanguage('addons/RelatedTopics');
// Lets build a settings form
require_once(SUBSDIR . '/SettingsForm.class.php');
// Instantiate the form
$rtSettings = new Settings_Form();
$config_vars = array(
array('check', 'relatedTopicsEnabled'),
array('int', 'relatedTopicsCount'),
);
// Load the settings to the form class
$rtSettings->settings($config_vars);
// Saving?
if (isset($_GET['save']))
{
checkSession('post');
saveDBSettings($config_vars);
writeLog();
Settings_Form::save_db($config_vars);
redirectexit('action=admin;area=relatedtopics;sa=settings');
}
$context['settings_title'] = $txt['admin_related_topics_settings'];
$context['page_title'] = $context['settings_title'] = $txt['admin_related_topics_settings'];
$context['sub_template'] = 'show_settings';
$context['post_url'] = $scripturl . '?action=admin;area=relatedtopics;save;sa=settings;';
Settings_Form::prepare_db($config_vars);
}
The current package is attached.
I got the settings working. Now if I can finish this "methods" part, this addon can soon be published to addons site. I got problem in initRelated();. If it is commented out, the code seems to work, partly But leaving it as it is, I only got a blank page.
The relevant last code is as follows:
function RelatedTopicsAdminMethods()
{
global $context, $modSettings, $scripturl, $user_info, $txt, $db_type;
$db = database();
initRelated();
$relatedIndexes = !empty($modSettings['relatedIndex']) ? explode(',', $modSettings['relatedIndex']) : array();
$context['related_methods'] = array(
'fulltext' => array(
'name' => $txt['relatedFulltext'],
'selected' => false,
'supported' => $db_type == 'mysql',
),
);
foreach ($context['related_methods'] as $id => $dummy)
$context['related_methods'][$id]['selected'] = in_array($id, $relatedIndexes);
if (isset($_GET['save']))
{
checkSession('post');
$methods = array();
if (isset($_POST['related_methods']))
{
foreach ($_POST['related_methods'] as $method)
{
if (isset($context['related_methods'][$method]) && $context['related_methods'][$method]['supported'])
$methods[] = $method;
}
}
updateSettings(array(
'relatedIndex' => implode(',', $methods),
'relatedIgnoredboards' => !empty($_POST['ignored_boards']) ? implode(',', $_POST['ignored_boards']) : '',
));
redirectexit('action=admin;area=relatedtopics;sa=methods');
}
$request = $db->query('', '
SELECT b.id_board, b.name, c.id_cat, c.name AS cat_name
FROM {db_prefix}boards AS b
LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
WHERE b.redirect = {string:blank_redirect}'. (!empty($modSettings['recycle_enable']) && !empty($modSettings['recycle_board']) ? '
AND NOT b.id_board = {int:recyle_board}' : ''),
array(
'blank_redirect' => '',
'recyle_board' => $modSettings['recycle_board'],
)
);
$context['categories'] = array();
while ($row = $db->fetch_assoc($request))
{
if (!isset($context['categories'][$row['id_cat']]))
$context['categories'][$row['id_cat']] = array(
'id' => $row['id_cat'],
'name' => $row['cat_name'],
'boards' => array(),
);
$context['categories'][$row['id_cat']]['boards'][$row['id_board']] = array(
'id' => $row['id_board'],
'name' => $row['name'],
'selected' => in_array($row['id_board'], $context['rt_ignore']),
);
}
$db->free_result($request);
$context['sub_template'] = 'related_topics_admin_methods';
}
function RelatedTopicsAdminBuildIndex()
{
global $scripturl, $modSettings, $context, $txt;
$db = database();
loadTemplate('Admin');
loadLanguage('Admin');
if (!isset($context['relatedClass']) && !initRelated())
fatal_lang_error('no_methods_selected');
$context['step'] = empty($_REQUEST['step']) ? 0 : (int) $_REQUEST['step'];
if ($context['step'] == 0)
{
// Clear caches
foreach ($context['relatedClass'] as $class)
$class->recreateIndexTables();
$db->query('', '
DELETE FROM {db_prefix}related_topics'
);
}
$request = $db->query('', '
SELECT MAX(id_topic)
FROM {db_prefix}topics');
list ($max_topics) = $db->fetch_row($request);
$db->free_result($request);
// How many topics to do per page load?
$perStep = 150;
$last = $context['step'] + $perStep;
// Search for topic ids between first and last which are not in ignored boards
$request = $db->query('', '
SELECT t.id_topic
FROM {db_prefix}topics AS t
WHERE t.id_topic > {int:start}
AND t.id_topic <= {int:last}' . (!empty($context['rt_ignore']) ? '
AND t.id_board NOT IN({array_int:ignored})' : ''),
array(
'start' => $context['step'],
'last' => $last,
'ignored' => $context['rt_ignore'],
)
);
$topics = array();
while ($row = $db->fetch_assoc($request))
$topics[] = $row['id_topic'];
$db->free_result($request);
// Update topics
relatedUpdateTopics($topics, true);
if ($last >= $max_topics)
redirectexit('action=admin;area=relatedtopics;sa=methods');
$context['sub_template'] = 'not_done';
$context['continue_get_data'] = '?action=admin;area=relatedtopics;sa=buildIndex;step=' . $last;
$context['continue_percent'] = round(100 * ($last / $max_topics));
$context['continue_post_data'] = '';
$context['continue_countdown'] = '2';
obExit();
}
The latest package is attached.
On a related note, you can use some hooks for this.
For the search in Topic.subs.php, you can use "integrate_remove_topics" as you probably don't need to have the related topics removed for recycled topics. I am going to register an issue to have a hook added before the return though.
In Post.subs.php, the first operation should use "integrate_create_topic". Either way, if the topic isn't created, you'll have a orphaned info there. You should really use the hook.
On the second operation, your mod already breaks with 1.1. It is kind of hard to understand what is going on here. Not really sure what to do here as modifyPost() is kind of hard to figure out all of the stuff that's going on. I'd say that it would make sense to add another hook there. Just bear in mind that your mod is going to break with 1.1 because there is updateSubjectStats(). So, maybe just use the comment to make it future proof?
Use "integrate_display_topic" in the Display.controller.php instead
SiteDispatcher.class.php should use "integrate_actions".
I think a feature request is born in this. Add a new operation for install.xml: <add-action action="related" file="Subs-Related.php" controller="Related" method="action_related" />. Then we can just move all of the actions to a new file which would be a simple array. The package manager would add/remove elements in the array and just write the new array to the file.
I haven't really checked anything in your mod besides the install file. Remember, the more you use hooks, the less work you'll have in the future and the more likely it will stay alive for longer. If you need help with how to use them, let me know.
If you're not sure, this is what you would use and then just add hooks. Hopefully this works.
<?php
/**
* This file contains all of the hook callbacks for the Related Topics Mod
*/
class RelatedTopicsHooks
{
/**
* Called from Topic.subs.php
* call_integration_hook('integrate_remove_topics', array($topics));
*/
public static function removeTopics(array $topics)
{
require_once(SOURCEDIR . '/Subs-Related.php');
relatedRemoveTopics($topics);
}
/**
* Post.subs.php
* call_integration_hook('integrate_create_topic', array($msgOptions, $topicOptions, $posterOptions));
*/
public static function createTopic(array $msgOptions, array $topicOptions, array $posterOptions)
{
require_once(SOURCEDIR . '/Subs-Related.php');
relatedUpdateTopics($topicOptions['id']);
}
/**
* Display.controller.php
* call_integration_hook('integrate_display_topic', array($topicinfo));
*/
public static function displayTopic(array $topicinfo)
{
global $topic;
if (!empty($modSettings['relatedTopicsEnabled']))
{
require_once(SOURCEDIR . '/Subs-Related.php');
loadRelated($topic);
}
}
/**
* SiteDispatcher.class.php
* call_integration_hook('integrate_actions', array(&$actionArray, &$adminActions));
*/
public static function addAction(array $actionArray, array $adminActions)
{
$actionArray['removetopic2'] => array('RemoveTopic.controller.php', 'RemoveTopic_Controller', 'action_removetopic2');
}
}
BTW, you are doing global SOURCEDIR in your install.xml file ;)
I would add docblocks to it so you know what you are expecting in each of the functions.
Thank you
@Joshua Dickerson . You advise is highly appreciated. I already finished packaging the manual version of this addon. But the hook version is relatively no so easy. :(
Still testing both versions of this addon. Any interested parties can beta test them. Attached are both versions of the addon.
I realized that I cannot get language file to load in RelatedTopic.101, so I end up with 90% hook. I am not so sure what is the reason for that yet. There could be a bug, so beware and do report. Anyway, I attached the 90% hook package for beta tester. I hope this is a working package since I cannot test it without data. Please do confirm if this package is working as I wish to add it in the addons board soon.
$actionArray['related'] = array('RelatedTopics.Subs.php', 'Related');
I can't see that function (Related) in that file.
I'm not sure why the language is not loaded, try removing the addons dir and see if that's the cause.