Skip to main content
Topic: Porting Related Topics Mod (Read 4285 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Porting Related Topics Mod

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:

Code: [Select]
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.

Re: Porting Related Topics Mod

Reply #1

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.
Bugs creator.
Features destroyer.
Template killer.

Re: Porting Related Topics Mod

Reply #2

Hurmmm... Could this be caused by wrongly used $db and $dbtbl? Maybe I recheck this too later.

Re: Porting Related Topics Mod

Reply #3

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.

Re: Porting Related Topics Mod

Reply #4

hmm... I guess you wrote $db->db_table_structure instead of $dbtbl->db_table_structure ;)

Anyway there is also a
Code: [Select]
$dbtbl->db_table_structure('{db_prefix}' . $table_name, $table['columns'], $table['indexes']);
that should likely be
Code: [Select]
$dbtbl->db_create_table(...);
the one in the
Code: [Select]
if (!$tableExists && empty($table['elk']))
condition.

Anyway, what I would do is:
* remove
Code: [Select]
$tableExists = in_array($db_prefix . $table_name, $existingTables);
then, instead of
Code: [Select]
		if (!$tableExists && empty($table['elk']))
$dbtbl->db_table_structure('{db_prefix}' . $table_name, $table['columns'], $table['indexes']);
// Update table
else
use
Code: [Select]
$tableExists = $dbtbl->db_create_table(...);
if ($tableExists === false)
Bugs creator.
Features destroyer.
Template killer.

Re: Porting Related Topics Mod

Reply #5

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.[1] Hope some one can point its misake(s). ;)

Code: [Select]
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 think I can make this addon works if there is no need for "methods" by moving to its settings to miscellaneous settings but that is not preferred for now.

Re: Porting Related Topics Mod

Reply #6

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 [1] But leaving it as it is, I only got a blank page.

The relevant last code is as follows:
Code: [Select]
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.
As I still has $context['rt_ignore'] to take care of.

Re: Porting Related Topics Mod

Reply #7

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.

Re: Porting Related Topics Mod

Reply #8

If you're not sure, this is what you would use and then just add hooks. Hopefully this works.

Code: [Select]
<?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.

Re: Porting Related Topics Mod

Reply #9

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.[1]
RT.100 is manual version.

Re: Porting Related Topics Mod

Reply #10

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.

Re: Porting Related Topics Mod

Reply #11

Code: [Select]
$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.
Bugs creator.
Features destroyer.
Template killer.