News:

Bored?  Looking to kill some time?  Want to chat with other SMF users?  Join us in IRC chat or Discord

Main Menu

Where does the $_GET thing happen for "board" and "topic"?

Started by Jade Elizabeth, April 11, 2015, 03:34:55 AM

Previous topic - Next topic

Jade Elizabeth

So I am creating a new section and I want it handled similarly to boards and topics. The section is a works area where ?work= is ?topic= and ?type= is ?board=. I have all of the sources, templates, etc I need but something is missing because it's not working as expected. When I go to any page it now says "The database value you're trying to insert does not exist: current_type"

I assume this is because I changed "current_board" to "current_type" in my function "loadType". My function and the loadBoard function are virtually the same with terminology changes, so I am wondering if there is something outside of load.php I am missing which checks for topic or board requests? Or deals with "current_board"? I've searched extensively but am at a loss.


Pretty sure they won't help but here are the load board and type functions from Load.php just in case :). As you can see they both call the get function well after using it so I am completely unsure how it works.
loadBoard:
function loadBoard()
{
global $txt, $scripturl, $context, $modSettings;
global $board_info, $board, $topic, $user_info, $smcFunc;

// Assume they are not a moderator.
$user_info['is_mod'] = false;
$context['user']['is_mod'] = &$user_info['is_mod'];

// Start the linktree off empty..
$context['linktree'] = array();

// Have they by chance specified a message id but nothing else?
if (empty($_REQUEST['action']) && empty($topic) && empty($board) && !empty($_REQUEST['msg']))
{
// Make sure the message id is really an int.
$_REQUEST['msg'] = (int) $_REQUEST['msg'];

// Looking through the message table can be slow, so try using the cache first.
if (($topic = cache_get_data('msg_topic-' . $_REQUEST['msg'], 120)) === null)
{
$request = $smcFunc['db_query']('', '
SELECT id_topic
FROM {db_prefix}messages
WHERE id_msg = {int:id_msg}
LIMIT 1',
array(
'id_msg' => $_REQUEST['msg'],
)
);

// So did it find anything?
if ($smcFunc['db_num_rows']($request))
{
list ($topic) = $smcFunc['db_fetch_row']($request);
$smcFunc['db_free_result']($request);
// Save save save.
cache_put_data('msg_topic-' . $_REQUEST['msg'], $topic, 120);
}
}

// Remember redirection is the key to avoiding fallout from your bosses.
if (!empty($topic))
redirectexit('topic=' . $topic . '.msg' . $_REQUEST['msg'] . '#msg' . $_REQUEST['msg']);
else
{
loadPermissions();
loadTheme();
fatal_lang_error('topic_gone', false);
}
}

// Load this board only if it is specified.
if (empty($board) && empty($topic))
{
$board_info = array('moderators' => array(), 'moderator_groups' => array());
return;
}

if (!empty($modSettings['cache_enable']) && (empty($topic) || $modSettings['cache_enable'] >= 3))
{
// @todo SLOW?
if (!empty($topic))
$temp = cache_get_data('topic_board-' . $topic, 120);
else
$temp = cache_get_data('board-' . $board, 120);

if (!empty($temp))
{
$board_info = $temp;
$board = $board_info['id'];
}
}

if (empty($temp))
{
$request = $smcFunc['db_query']('', '
SELECT
c.id_cat, b.name AS bname, b.description, b.num_topics, b.member_groups, b.deny_member_groups,
b.id_parent, c.name AS cname, IFNULL(mg.id_group, 0) AS id_moderator_group, mg.group_name,
IFNULL(mem.id_member, 0) AS id_moderator,
mem.real_name' . (!empty($topic) ? ', b.id_board' : '') . ', b.child_level,
b.id_theme, b.override_theme, b.count_posts, b.id_profile, b.redirect,
b.unapproved_topics, b.unapproved_posts' . (!empty($topic) ? ', t.approved, t.id_member_started' : '') . '
FROM {db_prefix}boards AS b' . (!empty($topic) ? '
INNER JOIN {db_prefix}topics AS t ON (t.id_topic = {int:current_topic})' : '') . '
LEFT JOIN {db_prefix}categories AS c ON (c.id_cat = b.id_cat)
LEFT JOIN {db_prefix}moderator_groups AS modgs ON (modgs.id_board = {raw:board_link})
LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = modgs.id_group)
LEFT JOIN {db_prefix}moderators AS mods ON (mods.id_board = {raw:board_link})
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = mods.id_member)
WHERE b.id_board = {raw:board_link}',
array(
'current_topic' => $topic,
'board_link' => empty($topic) ? $smcFunc['db_quote']('{int:current_board}', array('current_board' => $board)) : 't.id_board',
)
);
// If there aren't any, skip.
if ($smcFunc['db_num_rows']($request) > 0)
{
$row = $smcFunc['db_fetch_assoc']($request);

// Set the current board.
if (!empty($row['id_board']))
$board = $row['id_board'];

// Basic operating information. (globals... :/)
$board_info = array(
'id' => $board,
'moderators' => array(),
'moderator_groups' => array(),
'cat' => array(
'id' => $row['id_cat'],
'name' => $row['cname']
),
'name' => $row['bname'],
'description' => $row['description'],
'num_topics' => $row['num_topics'],
'unapproved_topics' => $row['unapproved_topics'],
'unapproved_posts' => $row['unapproved_posts'],
'unapproved_user_topics' => 0,
'parent_boards' => getBoardParents($row['id_parent']),
'parent' => $row['id_parent'],
'child_level' => $row['child_level'],
'theme' => $row['id_theme'],
'override_theme' => !empty($row['override_theme']),
'profile' => $row['id_profile'],
'redirect' => $row['redirect'],
'recycle' => !empty($modSettings['recycle_enable']) && !empty($modSettings['recycle_board']) && $modSettings['recycle_board'] == $board,
'posts_count' => empty($row['count_posts']),
'cur_topic_approved' => empty($topic) || $row['approved'],
'cur_topic_starter' => empty($topic) ? 0 : $row['id_member_started'],
);

// Load the membergroups allowed, and check permissions.
$board_info['groups'] = $row['member_groups'] == '' ? array() : explode(',', $row['member_groups']);
$board_info['deny_groups'] = $row['deny_member_groups'] == '' ? array() : explode(',', $row['deny_member_groups']);

do
{
if (!empty($row['id_moderator']))
$board_info['moderators'][$row['id_moderator']] = array(
'id' => $row['id_moderator'],
'name' => $row['real_name'],
'href' => $scripturl . '?action=profile;u=' . $row['id_moderator'],
'link' => '<a href="' . $scripturl . '?action=profile;u=' . $row['id_moderator'] . '">' . $row['real_name'] . '</a>'
);

if (!empty($row['id_moderator_group']))
$board_info['moderator_groups'][$row['id_moderator_group']] = array(
'id' => $row['id_moderator_group'],
'name' => $row['group_name'],
'href' => $scripturl . '?action=groups;sa=members;group=' . $row['id_moderator_group'],
'link' => '<a href="' . $scripturl . '?action=groups;sa=members;group=' . $row['id_moderator_group'] . '">' . $row['group_name'] . '</a>'
);
}
while ($row = $smcFunc['db_fetch_assoc']($request));

// If the board only contains unapproved posts and the user isn't an approver then they can't see any topics.
// If that is the case do an additional check to see if they have any topics waiting to be approved.
if ($board_info['num_topics'] == 0 && $modSettings['postmod_active'] && !allowedTo('approve_posts'))
{
// Free the previous result
$smcFunc['db_free_result']($request);

// @todo why is this using id_topic?
// @todo Can this get cached?
$request = $smcFunc['db_query']('', '
SELECT COUNT(id_topic)
FROM {db_prefix}topics
WHERE id_member_started={int:id_member}
AND approved = {int:unapproved}
AND id_board = {int:board}',
array(
'id_member' => $user_info['id'],
'unapproved' => 0,
'board' => $board,
)
);

list ($board_info['unapproved_user_topics']) = $smcFunc['db_fetch_row']($request);
}

if (!empty($modSettings['cache_enable']) && (empty($topic) || $modSettings['cache_enable'] >= 3))
{
// @todo SLOW?
if (!empty($topic))
cache_put_data('topic_board-' . $topic, $board_info, 120);
cache_put_data('board-' . $board, $board_info, 120);
}
}
else
{
// Otherwise the topic is invalid, there are no moderators, etc.
$board_info = array(
'moderators' => array(),
'moderator_groups' => array(),
'error' => 'exist'
);
$topic = null;
$board = 0;
}
$smcFunc['db_free_result']($request);
}

if (!empty($topic))
$_GET['board'] = (int) $board;

if (!empty($board))
{
// Get this into an array of keys for array_intersect
$moderator_groups = array_keys($board_info['moderator_groups']);

// Now check if the user is a moderator.
$user_info['is_mod'] = isset($board_info['moderators'][$user_info['id']]) || count(array_intersect($user_info['groups'], $moderator_groups)) != 0;

if (count(array_intersect($user_info['groups'], $board_info['groups'])) == 0 && !$user_info['is_admin'])
$board_info['error'] = 'access';
if (!empty($modSettings['deny_boards_access']) && count(array_intersect($user_info['groups'], $board_info['deny_groups'])) != 0 && !$user_info['is_admin'])
$board_info['error'] = 'access';

// Build up the linktree.
$context['linktree'] = array_merge(
$context['linktree'],
array(array(
'url' => $scripturl . '#c' . $board_info['cat']['id'],
'name' => $board_info['cat']['name']
)),
array_reverse($board_info['parent_boards']),
array(array(
'url' => $scripturl . '?board=' . $board . '.0',
'name' => $board_info['name']
))
);
}

// Set the template contextual information.
$context['user']['is_mod'] = &$user_info['is_mod'];
$context['current_topic'] = $topic;
$context['current_board'] = $board;

// No posting in redirection boards!
if (!empty($_REQUEST['action']) && $_REQUEST['action'] == 'post' && !empty($board_info['redirect']))
$board_info['error'] == 'post_in_redirect';

// Hacker... you can't see this topic, I'll tell you that. (but moderators can!)
if (!empty($board_info['error']) && (!empty($modSettings['deny_boards_access']) || $board_info['error'] != 'access' || !$user_info['is_mod']))
{
// The permissions and theme need loading, just to make sure everything goes smoothly.
loadPermissions();
loadTheme();

$_GET['board'] = '';
$_GET['topic'] = '';

// The linktree should not give the game away mate!
$context['linktree'] = array(
array(
'url' => $scripturl,
'name' => $context['forum_name_html_safe']
)
);

// If it's a prefetching agent or we're requesting an attachment.
if ((isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') || (!empty($_REQUEST['action']) && $_REQUEST['action'] === 'dlattach'))
{
ob_end_clean();
header('HTTP/1.1 403 Forbidden');
die;
}
elseif ($board_info['error'] == 'post_in_redirect')
{
// Slightly different error message here...
fatal_lang_error('cannot_post_redirect', false);
}
elseif ($user_info['is_guest'])
{
loadLanguage('Errors');
is_not_guest($txt['topic_gone']);
}
else
fatal_lang_error('topic_gone', false);
}

if ($user_info['is_mod'])
$user_info['groups'][] = 3;
}


loadType
function loadType()
{
global $txt, $scripturl, $context, $modSettings;
global $type_info, $type, $work, $user_info, $smcFunc;

// Start the linktree off empty..
$context['linktree'] = array();

// Have they by chance specified a work id but nothing else?
if (empty($_REQUEST['action']) && empty($work) && empty($type) && !empty($_REQUEST['cmt']))
{
// Make sure the message id is really an int.
$_REQUEST['cmt'] = (int) $_REQUEST['cmt'];
$_REQUEST['type'] = (int) $_REQUEST['type'];
$_REQUEST['work'] = (int) $_REQUEST['work'];

// Looking through the work table can be slow, so try using the cache first.
if (($work = cache_get_data('work-' . $_REQUEST['cmt'], 120)) === null)
{
$request = $smcFunc['db_query']('', '
SELECT id_work
FROM {db_prefix}works_works
WHERE id_work = {int:id_work}
LIMIT 1',
array(
'id_work' => $_REQUEST['work'],
)
);

// So did it find anything?
if ($smcFunc['db_num_rows']($request))
{
list ($work) = $smcFunc['db_fetch_row']($request);
$smcFunc['db_free_result']($request);
// Save save save.
cache_put_data('work-' . $_REQUEST['work'], $work, 120);
}
}

// Remember redirection is the key to avoiding fallout from your bosses.
if (!empty($work))
redirectexit('work=' . $work . '.cmt' . $_REQUEST['cmt'] . '#cmt' . $_REQUEST['cmt']);
else
{
loadPermissions();
loadTheme();
fatal_lang_error('topic_gone', false);
}
}

if (!empty($modSettings['cache_enable']) && (empty($work) || $modSettings['cache_enable'] >= 3))
{
// @todo SLOW?
if (!empty($work))
$temp = cache_get_data('work_type-' . $work, 120);
else
$temp = cache_get_data('type-' . $type, 120);

if (!empty($temp))
{
$type_info = $temp;
$type = $type_info['id'];
}
}

if (empty($temp))
{
$request = $smcFunc['db_query']('', '
SELECT
c.id_cat,
c.cat_name,
t.id_type,
t.type_name,
t.type_desc,
t.num_works,
t.num_comments,
' . (!empty($work) ? ', w.id_work' : '') . ',
t.child_level,
w.id_work,
w.id_member,
mg.group_name,
m.real_name,
w.work_title,
w.work_cap,
u.filetype,
u.location,
w.id_feedback,
w.id_series,
w.id_triggers,
w.is_adult,
w.poster_time,
w.work_comments,
w.work_views
FROM
{db_prefix}works_uploads as u
LEFT JOIN
{db_prefix}works_works AS w ON (w.id_work = u.id_work)
LEFT JOIN
{db_prefix}members AS m ON (m.id_member = w.id_member)
LEFT JOIN
{db_prefix}membergroups AS mg ON (mg.id_group = m.id_group)
LEFT JOIN
{db_prefix}works_categories AS c ON (t.id_cat = c.id_cat)
LEFT JOIN
{db_prefix}works_types AS t ON (t.id_type = w.id_type)
WHERE
t.id_type = {raw:type_link}',
array(
'current_work' => $work,
'type_link' => empty($work) ? $smcFunc['db_quote']('{int:current_type}', array('current_type' => $type)) : 't.id_type',
)
);
// If there aren't any, skip.
if ($smcFunc['db_num_rows']($request) > 0)
{
$row = $smcFunc['db_fetch_assoc']($request);

// Set the current board.
if (!empty($row['id_type']))
$type = $row['id_type'];

// Basic operating information. (globals... :/)
$type_info = array(
'id' => $type,
'cat' => array(
'id' => $row['id_cat'],
'name' => $row['cat_name']
),
'name' => $row['type_name'],
'description' => $row['type_desc'],
'num_comments' => comma_format($row['num_comments']),
'num_works' => comma_format($row['num_works']),
'parent' => $row['id_parent'],
'child_level' => $row['child_level'],
);

if (!empty($modSettings['cache_enable']) && (empty($work) || $modSettings['cache_enable'] >= 3))
{
// @todo SLOW?
if (!empty($work))
cache_put_data('work_type-' . $work, $type_info, 120);
cache_put_data('type-' . $type, $type_info, 120);
}
}
else
{
// Otherwise the topic is invalid, there are no moderators, etc.
$type_info = array(
'error' => 'exist'
);
$work = null;
$type = 0;
}
$smcFunc['db_free_result']($request);
}

if (!empty($work))
$_GET['type'] = (int) $type;

if (!empty($type))
{

// Build up the linktree.
$context['linktree'] = array_merge(
$context['linktree'],
array(array(
'url' => $scripturl . '#c' . $type_info['cat']['id'],
'name' => $type_info['cat']['name']
)),
array(array(
'url' => $scripturl . '?type=' . $type . '.0',
'name' => $type_info['name']
))
);
}

// Set the template contextual information.
$context['current_work'] = $work;
$context['current_type'] = $type;

// Hacker... you can't see this topic, I'll tell you that. (but moderators can!)
if (!empty($type_info['error']))
{
// The permissions and theme need loading, just to make sure everything goes smoothly.
loadPermissions();
loadTheme();

$_GET['type'] = '';
$_GET['work'] = '';

// The linktree should not give the game away mate!
$context['linktree'] = array(
array(
'url' => $scripturl,
'name' => $context['forum_name_html_safe']
)
);

// If it's a prefetching agent or we're requesting an attachment.
if ((isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') || (!empty($_REQUEST['action']) && $_REQUEST['action'] === 'dlattach'))
{
ob_end_clean();
header('HTTP/1.1 403 Forbidden');
die;
}
elseif ($user_info['is_guest'])
{
loadLanguage('Errors');
is_not_guest($txt['topic_gone']);
}
else
fatal_lang_error('topic_gone', false);
}

}
Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

live627

I think it's in Querystring.php in the function that cleans the request, not sure offhand though...


Suki

It won't work if you are just replacing $topic and $board.  Both variables are indeed mirrors from $_GET variables but are bizarrely used as globals inside the whole board/posting scope (and sometimes beyond!).

So, if you just did a replace, chances are those variables, $work and $type aren't actually defined anywhere which explains the SMF error you are seeing.

Without knowing what you are actually trying to do it will be pretty difficult to assist you.

In all honestly, cloning the whole board/topic procedure its a bad idea, if you really want to use it then don't clone it, just use it, save X specific amount of boards for it, let SMf do its business and just change the presentation of it.
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

Jade Elizabeth

Quote from: live627 on April 11, 2015, 08:21:52 AM
I think it's in Querystring.php in the function that cleans the request, not sure offhand though...

I did add a section to there, but it's not done me any good. Did I muck it up? It's just below the topic and board thing...

// Make sure $type and $work are numbers.
if (isset($_REQUEST['type']))
{
// Make sure its a string and not something else like an array
$_REQUEST['type'] = (string) $_REQUEST['type'];

// If there's a slash in it, we've got a start value! (old, compatible links.)
if (strpos($_REQUEST['type'], '/') !== false)
list ($_REQUEST['type'], $_REQUEST['start']) = explode('/', $_REQUEST['type']);
// Same idea, but dots.  This is the currently used format - ?board=1.0...
elseif (strpos($_REQUEST['type'], '.') !== false)
list ($_REQUEST['type'], $_REQUEST['start']) = explode('.', $_REQUEST['type']);
// Now make absolutely sure it's a number.
$board = (int) $_REQUEST['type'];
$_REQUEST['start'] = isset($_REQUEST['start']) ? (int) $_REQUEST['start'] : 0;

// This is for "Who's Online" because it might come via POST - and it should be an int here.
$_GET['type'] = $type;
}
// Well, $board is going to be a number no matter what.
else
$type = 0;

// We've got work!
if (isset($_REQUEST['work']))
{
// Make sure its a string and not something else like an array
$_REQUEST['work'] = (string) $_REQUEST['work'];

// Slash means old, beta style, formatting.  That's okay though, the link should still work.
if (strpos($_REQUEST['work'], '/') !== false)
list ($_REQUEST['work'], $_REQUEST['start']) = explode('/', $_REQUEST['work']);
// Dots are useful and fun ;).  This is ?topic=1.15.
elseif (strpos($_REQUEST['work'], '.') !== false)
list ($_REQUEST['work'], $_REQUEST['start']) = explode('.', $_REQUEST['work']);

$work = (int) $_REQUEST['work'];

// Now make sure the online log gets the right number.
$_GET['work'] = $work;
}
else
$work = 0;


Quote from: Suki on April 11, 2015, 10:57:28 AM
It won't work if you are just replacing $topic and $board.  Both variables are indeed mirrors from $_GET variables but are bizarrely used as globals inside the whole board/posting scope (and sometimes beyond!).

So, if you just did a replace, chances are those variables, $work and $type aren't actually defined anywhere which explains the SMF error you are seeing.

Without knowing what you are actually trying to do it will be pretty difficult to assist you.

In all honestly, cloning the whole board/topic procedure its a bad idea, if you really want to use it then don't clone it, just use it, save X specific amount of boards for it, let SMf do its business and just change the presentation of it.

I'm making a new section called "works". There's a workindex much like the boardindex, there's a type index like messageindex, and there's a work page similar to display and a post page that is completely different but will work the same in the body part.

I already have it as boards/topics displaying different and am not interested in that approach, I need them separate. I need them to be separate entities and I need them to be stored and treated differently, not just displayed differently. So I am making a new area. Because someone convinced me I should stick with SMF and build it in there I am doing my best but honestly it's a really tough learning curve and I'd really appreciate pointers every now and then :D.
Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

Jade Elizabeth

Okay I got it to work, I forgot to global things :/. Suki's post made me realise I forgot to double check ha ha.
Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

Jade Elizabeth

Now it's throwing the same error but only when I click on a type; when I click a type like "drawing" it goes to ?type=16 like it should but it's saying "The database value you're trying to insert does not exist: current_type" again. I've double checked I've globalled everything (I have) but it's not working.

Here's the query (updated) giving the trouble, from load.php.
function loadType()
{
global $txt, $scripturl, $context, $modSettings;
global $type_info, $workType, $work, $user_info, $smcFunc;

// Start the linktree off empty..
$context['linktree'] = array();

// Have they by chance specified a work id but nothing else?
if (empty($_REQUEST['action']) && empty($work) && empty($workType) && !empty($_REQUEST['cmt']))
{
// Make sure the message id is really an int.
$_REQUEST['cmt'] = (int) $_REQUEST['cmt'];
$_REQUEST['type'] = (int) $_REQUEST['type'];
$_REQUEST['work'] = (int) $_REQUEST['work'];

// Looking through the work table can be slow, so try using the cache first.
if (($work = cache_get_data('work-' . $_REQUEST['cmt'], 120)) === null)
{
$request = $smcFunc['db_query']('', '
SELECT id_work
FROM {db_prefix}works_works
WHERE id_work = {int:id_work}
LIMIT 1',
array(
'id_work' => $_REQUEST['work'],
)
);

// So did it find anything?
if ($smcFunc['db_num_rows']($request))
{
list ($work) = $smcFunc['db_fetch_row']($request);
$smcFunc['db_free_result']($request);
// Save save save.
cache_put_data('work-' . $_REQUEST['work'], $work, 120);
}
}

// Remember redirection is the key to avoiding fallout from your bosses.
if (!empty($work))
redirectexit('work=' . $work . '.cmt' . $_REQUEST['cmt'] . '#cmt' . $_REQUEST['cmt']);
else
{
loadPermissions();
loadTheme();
fatal_lang_error('topic_gone', false);
}
}

if (!empty($modSettings['cache_enable']) && (empty($work) || $modSettings['cache_enable'] >= 3))
{
// @todo SLOW?
if (!empty($work))
$temp = cache_get_data('work_type-' . $work, 120);
else
$temp = cache_get_data('type-' . $type, 120);

if (!empty($temp))
{
$type_info = $temp;
$workType = $type_info['id'];
}
}

if (empty($temp))
{
$request = $smcFunc['db_query']('', '
SELECT
c.id_cat,
c.cat_name,
t.id_type,
t.type_name,
t.type_desc,
t.num_works,
t.num_comments,
' . (!empty($work) ? 'w.id_work,' : '') . '
t.child_level,
w.id_member,
mg.group_name,
m.real_name,
w.work_title,
w.work_cap,
u.filetype,
u.location,
w.id_feedback,
w.id_series,
w.id_triggers,
w.is_adult,
w.poster_time,
w.work_comments,
w.work_views
FROM
{db_prefix}works_uploads as u
LEFT JOIN
{db_prefix}works_works AS w ON (w.id_work = u.id_work)
LEFT JOIN
{db_prefix}members AS m ON (m.id_member = w.id_member)
LEFT JOIN
{db_prefix}membergroups AS mg ON (mg.id_group = m.id_group)
LEFT JOIN
{db_prefix}works_types AS t ON (t.id_type = w.id_type)
LEFT JOIN
{db_prefix}works_categories AS c ON (c.id_cat = t.id_cat)
WHERE
t.id_type = {raw:type_link}',
array(
'current_work' => $work,
'type_link' => empty($work) ? $smcFunc['db_quote']('{int:current_type}', array('current_type' => $workType)) : 't.id_type',
)
);
// If there aren't any, skip.
if ($smcFunc['db_num_rows']($request) > 0)
{
$row = $smcFunc['db_fetch_assoc']($request);

// Set the current board.
if (!empty($row['id_type']))
$workType = $row['id_type'];

// Basic operating information. (globals... :/)
$type_info = array(
'id' => $workType,
'cat' => array(
'id' => $row['id_cat'],
'name' => $row['cat_name']
),
'name' => $row['type_name'],
'description' => $row['type_desc'],
'num_comments' => comma_format($row['num_comments']),
'num_works' => comma_format($row['num_works']),
'parent' => $row['id_parent'],
'child_level' => $row['child_level'],
);

if (!empty($modSettings['cache_enable']) && (empty($work) || $modSettings['cache_enable'] >= 3))
{
// @todo SLOW?
if (!empty($work))
cache_put_data('work_type-' . $work, $type_info, 120);
cache_put_data('type-' . $workType, $type_info, 120);
}
}
else
{
// Otherwise the topic is invalid, there are no moderators, etc.
$type_info = array(
'error' => 'exist'
);
$work = null;
$workType = 0;
}
$smcFunc['db_free_result']($request);
}

if (!empty($work))
$_GET['type'] = (int) $workType;

if (!empty($workType))
{

// Build up the linktree.
$context['linktree'] = array_merge(
$context['linktree'],
array(array(
'url' => $scripturl . '#c' . $type_info['cat']['id'],
'name' => $type_info['cat']['name']
)),
array(array(
'url' => $scripturl . '?type=' . $workType . '.0',
'name' => $type_info['name']
))
);
}

// Set the template contextual information.
$context['current_work'] = $work;
$context['current_type'] = $workType;

// Hacker... you can't see this topic, I'll tell you that. (but moderators can!)
if (empty($type_info['error']))
{
// The permissions and theme need loading, just to make sure everything goes smoothly.
loadPermissions();
loadTheme();

$_GET['type'] = '';
$_GET['work'] = '';

// The linktree should not give the game away mate!
$context['linktree'] = array(
array(
'url' => $scripturl,
'name' => $context['forum_name_html_safe']
)
);

// If it's a prefetching agent or we're requesting an attachment.
if ((isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch') || (!empty($_REQUEST['action']) && $_REQUEST['action'] === 'dlattach'))
{
ob_end_clean();
header('HTTP/1.1 403 Forbidden');
die;
}
elseif ($user_info['is_guest'])
{
loadLanguage('Errors');
is_not_guest($txt['topic_gone']);
}
else
fatal_lang_error('topic_gone', false);
}

}


Specifically this line:
'type_link' => empty($work) ? $smcFunc['db_quote']('{int:current_type}', array('current_type' => $workType)) : 't.id_type',
Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

Suki

Quote
I already have it as boards/topics displaying different and am not interested in that approach, I need them separate. I need them to be separate entities and I need them to be stored and treated differently, not just displayed differently.

Then do it completely separate. The board/topic structure surely isn't designed to do what you are trying to do so don't force it on it.

It seems to me you need to re-evaluate what you want and how you will achieve it, design a proper architecture before start coding it.

Start simple, two tables, works and types, table works, at minimum, will have:

- work id (int)
- user id (int)
- type id (int)
- approved (int)
- other options, body, name, time, log, etc

types will have:

- type id
- name

That simple approach can give you enough flexibility to do what you want and how you want it and the queries will be far more simpler to write/follow.


Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

Jade Elizabeth

I have all of that stuff, and it's a lot more complex than "id" and "name"....there is a lot more to it than that and I am extremely proud of my database, it's just queries I have trouble with because I'm still learning joins and more complex stuff.

Right now I have 5 tables:
smf_works_categories (4 columns)
smf_works_comments (7 columns)
smf_works_types (10 columns)
smf_works_uploads (4 columns)
smf_works_works (28 columns)

Arantor told me that since it functions the same I should re-write the code to do what I want. That's what I am doing :). And it does function the same, just because it looks different means nothing - I can make my boardindex and message index look like that screenshot if I wanted to. In fact my boardindex right now looks pretty similar, it's just that the boards are listed like that instead of a list of recent topics (which I could also do similarly lol).

I'm having more trouble with this because I don't understand how SMF works like everyone else seems to, and it's hard to find help, and when I do find help no one seems to understand me :/. Also, that query isn't hard to understand or follow at all. It grabs a list of works and all the data needed for the work index to display.
Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

Suki

You aren't getting the point I'm try to make here.

You can have your tables as complex as you want as long as you have a way to easily inter-relate them.

You don't need all the code from boardIndex/messageIndex, theres stuff there you simple do not need. The queries do not need to be as complicated as the queries in boardindex are neither.

I am not talking about the view/design, I'm talking about your architecture, it seems you have a wrong focus on it.

Like I said, without fully knowing what you are trying to do, it will be pretty difficult to help you, perhaps posting the full list of your tables including the columns then I might be able to help you.


So, do fully explain what you mean by "a lot more complex", define everything you have so far.
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

Jade Elizabeth

I don't think the query is the issue, the issue is somewhere else. It's not replacing things properly. It shouldn't be asking for "current_type" like that it should be replacing the value with an integer and putting the end result in, current_type shouldn't even be there, I would assume if it can't replace it that it would be empty so it should look for nothing?

Also if I am to send the DB I will do so privately....so check your inbox for a dump (ha ha ha ;)). Please keep it confidential.

As for files I have:
WorkIndex.php
Subs-WorkIndex.php
TypeIndex.php
Subs-TypeIndex.php

TypeIndex.template.php
Workindex.template.php

I have edited:
Index.php
Load.php
QueryString.php
Subs.php (menu items)

Workindex displays a list of types, and a list of recent works.
Typeindex displays a list of works in that type and also will display the list of types, this time with sub types for its own type.
Works will display the actual work and comments (much like replies and topics except separated which has complicated things but I prefer it).
Submit will display an upload/post screen with many options.
Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

Suki

no, no, no no and double no...

I did not ask for the entire  DB!!!  :P only asked for your table structure, how many tables do you have and how many columns are inside those tables, what type those columns are, its names, table indexes etc, etc.

You don't need to mess with Load.php, that file is reserved for stuff that will appear everywhere.

I'm unsure how familiar you are with the MVC software architecture, it is basically organizing your stuff. SMF follows a similar pattern and might be easier to use SMF's approach than pure MVC so let use SMF as an example.

Besides your DB structure, the other important thing is your file structure, a basic, starter structure will be as follows (can be expanded, modified to your needs of course):

- WorkIndex.php  will act as your "Controller"
- Subs-Work-Index.php  will act as your "Model"
- WorkIndex.template.php will act as your view (in a more lose way)


Now, your entire architecture has more components:

Type, comments, categories.  Each can have its own MVC pattern if you want or can be incorporated into Work's, for the sake of keep it simple, lets incorporate them all into Work.

Since this is going to be a separate entity, it needs a separate action, I believe you mentioned you already had this, IE, action=work  and each actions within main action work will be handled by sub-actions, for example, deleting a work:

action=work;sa=delete;wid=1

Where "wid" its the work ID, didn't directly use ID because some not soe bright host has issues with it.

Now, inside your "controller" (WorkIndex.php) there has to be a "master" function, that function will act as a "router", that is, depending on the url it receives it will call the appropriate functions, this is called "separation of concerns".  Following the same delete example:

action=work;sa=delete;wid=1

Your "master" function will call your "delete" function, which will deal with deleting the work and any other data associated with that work like comments.

The act of modifying something is commonly known as "CRUD" which stands for Create, Read, Update Delete.

You don't need to have functions for all those options of course, it totally depends on what you need and what you want BUT, keep them completely separate from each other makes it incredible easy for you to add a new one if you so desire.

OK, next step, queries, thats where Subs-WorkIndex comes to play, going back to the delete example:

The master call received an url: action=work;sa=delete;wid=1
The master call called the delete function

The delete function did all pertinent checks and call the "actual delete" function.

This "actual delete" function's only duty is to perform the query that will delete the work form your DB, thats it, it shouldn't have any other checks or any other "ifs" or any other kind of logic, it just deals with performing the action it was coded for, on this case, deleting a work.

Now, when deleting a work you will also need to delete all other data associated with it, which data depends on what you need of course but to keep up with the example, lets assume you also need to delete all comments associated with that work.

This is where it gets interesting, where should I put the query to delete all comments? surely it can be included in the query to delete the work  or you could have a separate function on Subs-WorkIndex  to ONLY delete comments associated by a certain work ID, something like this:

function deleteCommentsByID($id)
{

}

This function will be called by your "controller" function delete in WorkIndex.php, so, that function will now do 2 things, call the function to delete a work and also call a function to delete any comments associated with that work.

controllerDelete()
{
  $id = $_REQUEST['id'];  // not ideal, just to give you an example

// delete all comments associated with this ID
deleteWork($id);

// delete all comments associated with that work ID
deleteCommentsByID($id);
}


The main idea behind doing is like this is to help you maintain/escalate your script easily, for example, lets say in the future you will want to add a rate system to each work and of course you will need to also delete those rates if a work is deleted, the only thiongs you will have to do is to add another function:

function deleteRatesByID($id)
{

}


And call that function in your controllerDelete function:

controllerDelete()
{
  $id = $_REQUEST['id'];  // not ideal, just to give you an example

// delete all comments associated with this ID
deleteWork($id);

// delete all comments associated with that work ID
deleteCommentsByID($id);

// delete all rates associated with this work ID
deleteRatesByID($id);
}


I hope you get the point I'm trying to make here, which is not how to delete a work BUT rather how to separate all your logic into smaller and more modular pieces you can call at anything time from anywhere.

I know this is prob something you aren't interested but believe me, before start messing with queries, it is important that you recognize this bits as it will help you tremendously with any other script.  So let me know if you got this concept so we may proceed with the main queries (to display a work) and how to approach them.
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

Jade Elizabeth

I understand you completely. I have built a system in this way using a framework, and I wanted to build a whole new one like this that would have a basic forum but Arantor talked me into building my system into SMF. But your explanation makes me really happy cause it's never been applied to SMF for me in a way I understood! Thank you :D.

I think the problem is I don't want it to be under ?action=works with sub actions, etc, I want it to show a work or type as ?type=x and ?work=x like how topics and board urls are....so I have to approach it differently but I'm struggling to understand how topics and boards do it as well ha ha.
Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

Suki

Doesn't really matter if you use action or your own word, the workflow is pretty much the same,  you still will have to use subactions to handle the CRUD actions for each work and types.

I once again will advice you to not mess with how topics and boards work, its sufficiently complicated for you to not understand it and just give up trying.  A better approach would be understanding how thes structures work form the very core and with a very simple approach, then you will start to understand how topic and board works, kinda like starting to understand how to multiply and divide before jumping to square roots and integrals and derivatives.
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

Jade Elizabeth

I understand what you're saying. I do know how SMF does the others, and I think I can see where it's getting the topic and board stuff in too.
Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

Jade Elizabeth

Have you got any idea what's causing this error or how to fix it?
Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

Jade Elizabeth

Alright so I typoed "type" somewhere. Very embarrassing!

But it's working now, except it's saying the type doesn't exist. Is there some way I can find out what the query is outputting or anything else so I can figure out where my logic is off? It should be looking at type 16, which has 20 results.
Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

live627


Jade Elizabeth

Sure!! :D Really appreciate you looking into it!!! :D

Load.php
function loadType()
{
global $txt, $scripturl, $context, $modSettings;
global $type_info, $workType, $work, $user_info, $smcFunc;

// Start the linktree off empty..
$context['linktree'] = array();

// Have they by chance specified a work id but nothing else?
if (empty($_REQUEST['action']) && empty($work) && empty($workType) && !empty($_REQUEST['cmt']))
{
// Make sure the message id is really an int.
$_REQUEST['cmt'] = (int) $_REQUEST['cmt'];
$_REQUEST['type'] = (int) $_REQUEST['type'];
$_REQUEST['work'] = (int) $_REQUEST['work'];

// Looking through the work table can be slow, so try using the cache first.
if (($work = cache_get_data('work-' . $_REQUEST['work'], 120)) === null)
{
$request = $smcFunc['db_query']('', '
SELECT id_work
FROM {db_prefix}works_works
WHERE id_work = {int:id_work}
LIMIT 1',
array(
'id_work' => $_REQUEST['work'],
)
);

// So did it find anything?
if ($smcFunc['db_num_rows']($request))
{
list ($work) = $smcFunc['db_fetch_row']($request);
$smcFunc['db_free_result']($request);
// Save save save.
cache_put_data('work-' . $_REQUEST['work'], $work, 120);
}
}

// Remember redirection is the key to avoiding fallout from your bosses.
if (!empty($work))
redirectexit('work=' . $work . '.cmt' . $_REQUEST['cmt'] . '#cmt' . $_REQUEST['cmt']);
else
{
loadPermissions();
loadTheme();
fatal_lang_error('topic_gone', false);
}
}

if (!empty($modSettings['cache_enable']) && (empty($work) || $modSettings['cache_enable'] >= 3))
{
// @todo SLOW?
if (!empty($work))
$temp = cache_get_data('work_type-' . $work, 120);
else
$temp = cache_get_data('type-' . $workType, 120);

if (!empty($temp))
{
$type_info = $temp;
$workType = $type_info['id'];
}
}

if (empty($temp))
{
$request = $smcFunc['db_query']('', '
SELECT
c.id_cat,
c.cat_name,
t.id_type,
t.id_parent,
t.type_name,
t.type_desc,
t.num_works,
t.num_comments,
' . (!empty($work) ? 'w.id_work,' : '') . '
t.child_level,
w.id_member,
mg.group_name,
m.real_name,
w.work_title,
w.work_cap,
u.filetype,
u.location,
w.id_feedback,
w.id_series,
w.id_triggers,
w.is_adult,
w.poster_time,
w.work_comments,
w.work_views
FROM
{db_prefix}works_uploads as u
LEFT JOIN
{db_prefix}works_works AS w ON (w.id_work = u.id_work)
LEFT JOIN
{db_prefix}members AS m ON (m.id_member = w.id_member)
LEFT JOIN
{db_prefix}membergroups AS mg ON (mg.id_group = m.id_group)
LEFT JOIN
{db_prefix}works_types AS t ON (t.id_type = w.id_type)
LEFT JOIN
{db_prefix}works_categories AS c ON (c.id_cat = t.id_cat)
WHERE
t.id_type = {raw:type_link}',
array(
'current_work' => $work,
'current_type' => $workType,
'type_link' => empty($work) ? $smcFunc['db_quote']('{int:current_type}', array('current_type' => $workType)) : 't.id_type',
)
);
// If there aren't any, skip.
if ($smcFunc['db_num_rows']($request) > 0)
{
$row = $smcFunc['db_fetch_assoc']($request);

// Set the current board.
if (!empty($row['id_type']))
$workType = $row['id_type'];

if (!empty($row['id_work']))
$work = $row['id_work'];

// Basic operating information. (globals... :/)
$type_info = array(
'id' => $workType,
'cat' => array(
'id' => $row['id_cat'],
'name' => $row['cat_name']
),
'name' => $row['type_name'],
'description' => $row['type_desc'],
'num_comments' => comma_format($row['num_comments']),
'num_works' => comma_format($row['num_works']),
'parent' => $row['id_parent'],
'child_level' => $row['child_level'],
);

if (!empty($modSettings['cache_enable']) && (empty($work) || $modSettings['cache_enable'] >= 3))
{
// @todo SLOW?
if (!empty($work))
cache_put_data('work_type-' . $work, $type_info, 120);
cache_put_data('type-' . $workType, $type_info, 120);
}
}
else
{
// Otherwise the topic is invalid, there are no moderators, etc.
$type_info = array(
'error' => 'exist'
);
$work = null;
$workType = 0;
}
$smcFunc['db_free_result']($request);
}

if (!empty($work))
$_GET['type'] = (int) $workType;

if (!empty($workType))
{

// Build up the linktree.
$context['linktree'] = array_merge(
$context['linktree'],
array(array(
'url' => $scripturl . '#c' . $type_info['cat']['id'],
'name' => $type_info['cat']['name']
)),
array(array(
'url' => $scripturl . '?type=' . $workType . '.0',
'name' => $type_info['name']
))
);
}

// Set the template contextual information.
$context['current_work'] = $work;
$context['current_type'] = $workType;

// Hacker... you can't see this topic, I'll tell you that. (but moderators can!)
if (empty($type_info['error']))
{
// The permissions and theme need loading, just to make sure everything goes smoothly.
loadPermissions();
loadTheme();

$_GET['type'] = '';
$_GET['work'] = '';

// The linktree should not give the game away mate!
$context['linktree'] = array(
array(
'url' => $scripturl,
'name' => $context['forum_name_html_safe']
)
);

// If it's a prefetching agent or we're requesting an attachment.
if ((isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch'))
{
ob_end_clean();
header('HTTP/1.1 403 Forbidden');
die;
}
elseif ($user_info['is_guest'])
{
loadLanguage('Errors');
is_not_guest($txt['topic_gone']);
}
else
fatal_lang_error('topic_gone', false);
}

}


Small part of typeindex.php (I have used the queries and they work, they should give 20 results for type 16 which it does so....also the subs file is roughly the same as the boardindex subs file and I have checked that and it works, but I can post that too if you need it :)).
function TypeIndex()
{
global $txt, $scripturl, $workType, $modSettings, $context, $work;
global $options, $settings, $type_info, $user_info, $smcFunc, $sourcedir;

if (WIRELESS)
$context['sub_template'] = WIRELESS_PROTOCOL . '_typeindex';
else
loadTemplate('TypeIndex');

if (!$user_info['is_guest'])
{
// We can't know they read it if we allow prefetches.
// But we'll actually mark it read later after we've done everything else.
if (isset($_SERVER['HTTP_X_MOZ']) && $_SERVER['HTTP_X_MOZ'] == 'prefetch')
{
ob_end_clean();
header('HTTP/1.1 403 Prefetch Forbidden');
die;
}
}

$context['name'] = $type_info['name'];
$context['description'] = $type_info['description'];
if (!empty($type_info['description']))
$context['meta_description'] = strip_tags($type_info['description']);

// How many topics do we have in total?
$type_info['total_works'] = $type_info['num_works'];

// View all the topics, or just a few?
$context['works_per_page'] = empty($modSettings['disableCustomPerPage']) && !empty($options['topics_per_page']) && !WIRELESS ? $options['topics_per_page'] : $modSettings['defaultMaxTopics'];
$context['comments_per_page'] = empty($modSettings['disableCustomPerPage']) && !empty($options['messages_per_page']) && !WIRELESS ? $options['messages_per_page'] : $modSettings['defaultMaxMessages'];
$maxindex = isset($_REQUEST['all']) && !empty($modSettings['enableAllMessages']) ? $type_info['total_works'] : $context['works_per_page'];

// Right, let's only index normal stuff!
if (count($_GET) > 1)
{
$session_name = session_name();
foreach ($_GET as $k => $v)
{
if (!in_array($k, array('type', 'start', $session_name)))
$context['robot_no_index'] = true;
}
}
if (!empty($_REQUEST['start']) && (!is_numeric($_REQUEST['start']) || $_REQUEST['start'] % $context['comments_per_page'] != 0))
$context['robot_no_index'] = true;

// We only know these.
if (isset($_REQUEST['sort']) && !in_array($_REQUEST['sort'], array('subject', 'starter', 'last_poster', 'replies', 'views', 'first_post', 'last_post')))
$_REQUEST['sort'] = 'last_post';

// Make sure the starting place makes sense and construct the page index.
if (isset($_REQUEST['sort']))
$context['page_index'] = constructPageIndex($scripturl . '?type=' . $workType . '.%1$d;sort=' . $_REQUEST['sort'] . (isset($_REQUEST['desc']) ? ';desc' : ''), $_REQUEST['start'], $type_info['total_works'], $maxindex, true);
else
$context['page_index'] = constructPageIndex($scripturl . '?type=' . $workType . '.%1$d', $_REQUEST['start'], $type_info['total_works'], $maxindex, true);
$context['start'] = &$_REQUEST['start'];

// Set a canonical URL for this page.
$context['canonical_url'] = $scripturl . '?type=' . $workType . '.' . $context['start'];

$can_show_all = !empty($modSettings['enableAllMessages']) && $maxindex > $modSettings['enableAllMessages'];

if (WIRELESS || !($can_show_all && isset($_REQUEST['all'])))
{
$context['links'] = array(
'first' => $_REQUEST['start'] >= $context['works_per_page'] ? $scripturl . '?type=' . $workType . '.0' : '',
'prev' => $_REQUEST['start'] >= $context['works_per_page'] ? $scripturl . '?type=' . $workType . '.' . ($_REQUEST['start'] - $context['works_per_page']) : '',
'next' => $_REQUEST['start'] + $context['works_per_page'] < $type_info['total_works'] ? $scripturl . '?type=' . $workType . '.' . ($_REQUEST['start'] + $context['works_per_page']) : '',
'last' => $_REQUEST['start'] + $context['works_per_page'] < $type_info['total_works'] ? $scripturl . '?type=' . $workType . '.' . (floor(($type_info['total_works'] - 1) / $context['works_per_page']) * $context['works_per_page']) : '',
'up' => $type_info['parent'] == 0 ? $scripturl . '?' : $scripturl . '?type=' . $type_info['parent'] . '.0'
);
}

$context['page_info'] = array(
'current_page' => $_REQUEST['start'] / $context['works_per_page'] + 1,
'num_pages' => floor(($type_info['total_works'] - 1) / $context['works_per_page']) + 1
);

if (isset($_REQUEST['all']) && $can_show_all)
{
$maxindex = $modSettings['enableAllMessages'];
$_REQUEST['start'] = 0;
}

// 'Print' the header and board info.
$context['page_title'] = strip_tags($type_info['name']);

// Set the variables up for the template.
$context['can_mark_notify'] = !$user_info['is_guest'];
$context['can_share_new'] = allowedTo('share_new');

require_once($sourcedir . '/Subs-TypeIndex.php');
$typeIndexOptions = array(
'include_categories' => false,
'base_level' => $type_info['child_level'] + 1,
'parent_id' => $type_info['id'],
);
$context['types'] = getTypeIndex($typeIndexOptions);

// Nosey, nosey - who's viewing this topic?
if (!empty($settings['display_who_viewing']))
{
$context['view_members'] = array();
$context['view_members_list'] = array();
$context['view_num_hidden'] = 0;

$request = $smcFunc['db_query']('', '
SELECT
lo.id_member, lo.log_time, mem.real_name, mem.member_name, mem.show_online,
mg.online_color, mg.id_group, mg.group_name
FROM {db_prefix}log_online AS lo
LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = lo.id_member)
LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = CASE WHEN mem.id_group = {int:reg_member_group} THEN mem.id_post_group ELSE mem.id_group END)
WHERE INSTR(lo.url, {string:in_url_string}) > 0 OR lo.session = {string:session}',
array(
'reg_member_group' => 0,
'in_url_string' => 's:5:"type";i:' . $workType . ';',
'session' => $user_info['is_guest'] ? 'ip' . $user_info['ip'] : session_id(),
)
);
while ($row = $smcFunc['db_fetch_assoc']($request))
{
if (empty($row['id_member']))
continue;

if (!empty($row['online_color']))
$link = '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '" style="color: ' . $row['online_color'] . ';">' . $row['real_name'] . '</a>';
else
$link = '<a href="' . $scripturl . '?action=profile;u=' . $row['id_member'] . '">' . $row['real_name'] . '</a>';

$is_buddy = in_array($row['id_member'], $user_info['buddies']);
if ($is_buddy)
$link = '<strong>' . $link . '</strong>';

if (!empty($row['show_online']) || allowedTo('moderate_forum'))
$context['view_members_list'][$row['log_time'] . $row['member_name']] = empty($row['show_online']) ? '<em>' . $link . '</em>' : $link;
// @todo why are we filling this array of data that are just counted (twice) and discarded? ???
$context['view_members'][$row['log_time'] . $row['member_name']] = array(
'id' => $row['id_member'],
'username' => $row['member_name'],
'name' => $row['real_name'],
'group' => $row['id_group'],
'href' => $scripturl . '?action=profile;u=' . $row['id_member'],
'link' => $link,
'is_buddy' => $is_buddy,
'hidden' => empty($row['show_online']),
);

if (empty($row['show_online']))
$context['view_num_hidden']++;
}
$context['view_num_guests'] = $smcFunc['db_num_rows']($request) - count($context['view_members']);
$smcFunc['db_free_result']($request);

// Put them in "last clicked" order.
krsort($context['view_members_list']);
krsort($context['view_members']);
}

// Default sort methods.
$sort_methods = array(
'subject' => 'w.work_title',
'starter' => 'IFNULL(m.real_name, w.id_member)',
'last_poster' => 'IFNULL(m.real_name, cl.poster_name)',
'replies' => 'w.num_comments',
'views' => 'w.num_views',
'first_post' => 'w.id_work',
'last_post' => 'w.id_last_com'
);

// They didn't pick one, default to by last post descending.
if (!isset($_REQUEST['sort']) || !isset($sort_methods[$_REQUEST['sort']]))
{
$context['sort_by'] = 'last_post';
$_REQUEST['sort'] = 'id_last_com';
$ascending = isset($_REQUEST['asc']);
}
// Otherwise default to ascending.
else
{
$context['sort_by'] = $_REQUEST['sort'];
$_REQUEST['sort'] = $sort_methods[$_REQUEST['sort']];
$ascending = !isset($_REQUEST['desc']);
}

$context['sort_direction'] = $ascending ? 'up' : 'down';
$txt['starter'] = $txt['started_by'];

foreach ($sort_methods as $key => $val)
$context['works_headers'][$key] = '<a href="' . $scripturl . '?type=' . $context['current_type'] . '.' . $context['start'] . ';sort=' . $key . ($context['sort_by'] == $key && $context['sort_direction'] == 'up' ? ';desc' : '') . '">' . $txt[$key] . ($context['sort_by'] == $key ? '<span class="sort sort_' . $context['sort_direction'] . '"></span>' : '') . '</a>';

// Calculate the fastest way to get the topics.
$start = (int) $_REQUEST['start'];
if ($start > ($type_info['total_works'] - 1) / 2)
{
$ascending = !$ascending;
$fake_ascending = true;
$maxindex = $type_info['total_works'] < $start + $maxindex + 1 ? $type_info['total_works'] - $start : $maxindex;
$start = $type_info['total_works'] < $start + $maxindex + 1 ? 0 : $type_info['total_works'] - $start - $maxindex;
}
else
$fake_ascending = false;

// Setup the default topic icons...
$context['icon_sources'] = array();
foreach ($context['stable_icons'] as $icon)
$context['icon_sources'][$icon] = 'images_url';

$work_ids = array();
$context['topics'] = array();

// Sequential pages are often not optimized, so we add an additional query.
$pre_query = $start > 0;
if ($pre_query && $maxindex > 0)
{
$request = $smcFunc['db_query']('', '
SELECT w.id_work
FROM {db_prefix}works_works AS w' . ($context['sort_by'] === 'last_poster' ? '
INNER JOIN {db_prefix}works_comments AS cl ON (cl.id_cmt = w.id_last_cmt)' : (in_array($context['sort_by'], array('starter', 'subject')) ? '
INNER JOIN {db_prefix}works_comments AS cf ON (cf.id_cmt = w.id_first_cmt)' : '')) . ($context['sort_by'] === 'starter' ? '
LEFT JOIN {db_prefix}members AS memf ON (memf.id_member = mf.id_member)' : '') . ($context['sort_by'] === 'last_poster' ? '
LEFT JOIN {db_prefix}members AS meml ON (meml.id_member = ml.id_member)' : '') . '
WHERE w.id_type = {int:current_type}
ORDER BY ' . ($fake_ascending ? '' : ' DESC') . ', ' . $_REQUEST['sort'] . ($ascending ? '' : ' DESC') . '
LIMIT {int:start}, {int:maxindex}',
array(
'current_type' => $workType,
'current_member' => $user_info['id'],
'is_approved' => 1,
'id_member_guest' => 0,
'start' => $start,
'maxindex' => $maxindex,
)
);
$work_ids = array();
while ($row = $smcFunc['db_fetch_assoc']($request))
$work_ids[] = $row['id_work'];
}

// Grab the appropriate topic information...
if (!$pre_query || !empty($work_ids))
{
// For search engine effectiveness we'll link guests differently.
$context['pageindex_multiplier'] = empty($modSettings['disableCustomPerPage']) && !empty($options['messages_per_page']) && !WIRELESS ? $options['messages_per_page'] : $modSettings['defaultMaxMessages'];

$result = $smcFunc['db_query']('substring', '
SELECT
w.id_work,
w.work_comments,
w.is_locked,
w.work_views,
w.work_favs,
' . ($user_info['is_guest'] ? '0' : 'IFNULL(lw.id_cmt, IFNULL(lwr.id_cmt, -1)) + 1') . ' AS new_from,
c.poster_time AS last_cmt_time,
c.id_member AS last_cmt_id_member,
meml.real_name AS last_cmt_name,
w.id_cmt_modified,
w.id_member AS work_author_id,
memf.real_name AS work_author,
w.work_title,
w.poster_time,
w.id_genre
FROM {db_prefix}works_works AS w
LEFT JOIN smf_works_comments AS c ON (c.id_comment = w.id_last_cmt)
LEFT JOIN smf_members AS meml ON (meml.id_member = c.id_member)
LEFT JOIN {db_prefix}members AS memf ON (memf.id_member = w.id_member)' . ($user_info['is_guest'] ? '' : '
LEFT JOIN {db_prefix}log_works AS lw ON (lw.id_work = w.id_work AND lw.id_member = {int:current_member})
LEFT JOIN {db_prefix}log_works_read AS lwr ON (lwr.id_type = {int:current_type} AND lwr.id_member = {int:current_member})') . '
WHERE ' . ($pre_query ? 'w.id_work IN ({array_int:work_list})' : 'w.id_type = {int:current_type}') . '
ORDER BY ' . ($pre_query ? 'FIND_IN_SET(w.id_work, {string:find_set_works})' : ($fake_ascending ? '' : ' DESC') . ', ' . $_REQUEST['sort'] . ($ascending ? '' : ' DESC')) . '
LIMIT ' . ($pre_query ? '' : '{int:start}, ') . '{int:maxindex}',
array(
'current_type' => $workType,
'current_member' => $user_info['id'],
'work_list' => $work_ids,
'is_approved' => 1,
'find_set_works' => implode(',', $work_ids),
'start' => $start,
'maxindex' => $maxindex,
)
);

// Begin 'printing' the message index for current board.
while ($row = $smcFunc['db_fetch_assoc']($result))
{
if (!$pre_query)
$work_ids[] = $row['id_work'];

// Censor titles
censorText($row['work_title']);

// Decide how many pages the topic should have.
if ($row['work_comments'] + 1 > $context['comments_per_page'])
{
$pages = '« ';

// We can't pass start by reference.
$start = -1;
$pages .= constructPageIndex($scripturl . '?work=' . $row['id_work'] . '.%1$d', $start, $row['work_comments'] + 1, $context['comments_per_page'], true, false);

// If we can use all, show all.
if (!empty($modSettings['enableAllMessages']) && $row['work_comments'] + 1 < $modSettings['enableAllMessages'])
$pages .= ' &nbsp;<a href="' . $scripturl . '?work=' . $row['id_work'] . '.0;all">' . $txt['all'] . '</a>';
$pages .= ' »';
}
else
$pages = '';

/* We need to check the topic icons exist...
if (!empty($modSettings['messageIconChecks_enable']))
{
if (!isset($context['icon_sources'][$row['first_icon']]))
$context['icon_sources'][$row['first_icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['first_icon'] . '.png') ? 'images_url' : 'default_images_url';
if (!isset($context['icon_sources'][$row['last_icon']]))
$context['icon_sources'][$row['last_icon']] = file_exists($settings['theme_dir'] . '/images/post/' . $row['last_icon'] . '.png') ? 'images_url' : 'default_images_url';
}
else
{
if (!isset($context['icon_sources'][$row['first_icon']]))
$context['icon_sources'][$row['first_icon']] = 'images_url';
if (!isset($context['icon_sources'][$row['last_icon']]))
$context['icon_sources'][$row['last_icon']] = 'images_url';
}*/


// 'Print' the topic info.
$context['works'][$row['id_work']] = array(
'id_work' => $row['id_work'],
'first_post' => array(
'id_work' => $row['id_work'],
'author' => array(
'name' => $row['work_author_name'],
'id' => $row['work_author_id'],
'href' => !empty($row['work_author_id']) ? $scripturl . '?action=profile;u=' . $row['work_author_id'] : '',
'link' => !empty($row['work_author_id']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row['work_author_id'] . '" title="' . $txt['profile_of'] . ' ' . $row['work_author_name'] . '" class="preview">' . $row['work_author_name'] . '</a>' : $row['work_author_name']
),
'time' => timeformat($row['poster_time']),
'timestamp' => forum_time(true, $row['poster_time']),
'title' => $row['work_title'],
'icon' => $row['id_genre'],
//'icon_url' => $settings[$context['icon_sources'][$row['first_icon']]] . '/post/' . $row['first_icon'] . '.png',
'href' => $scripturl . '?work=' . $row['id_work'] . '.0',
'link' => '<a href="' . $scripturl . '?work=' . $row['id_work'] . '.0">' . $row['work_title'] . '</a>'
),
'last_post' => array(
'id' => $row['id_last_cmt'],
'member' => array(
'name' => $row['last_cmt_name'],
'id' => $row['last_cmt_id_member'],
'href' => !empty($row['last_cmt_id_member']) ? $scripturl . '?action=profile;u=' . $row['last_cmt_id_member'] : '',
'link' => !empty($row['last_cmt_id_member']) ? '<a href="' . $scripturl . '?action=profile;u=' . $row['last_cmt_id_member'] . '">' . $row['last_cmt_name'] . '</a>' : $row['last_cmt_name']
),
'time' => timeformat($row['last_cmt_time']),
'timestamp' => forum_time(true, $row['last_cmt_time']),
'href' => $scripturl . '?work=' . $row['id_work'] . ($user_info['is_guest'] ? ('.' . (!empty($options['view_newest_first']) ? 0 : ((int) (($row['work_comments']) / $context['pageindex_multiplier'])) * $context['pageindex_multiplier']) . '#cmt' . $row['id_last_cmt']) : (($row['work_comments'] == 0 ? '.0' : '.cmt' . $row['id_last_cmt']) . '#new')),
'link' => '<a href="' . $scripturl . '?work=' . $row['id_work'] . ($user_info['is_guest'] ? ('.' . (!empty($options['view_newest_first']) ? 0 : ((int) (($row['work_comments']) / $context['pageindex_multiplier'])) * $context['pageindex_multiplier']) . '#cmt' . $row['id_last_cmt']) : (($row['work_comments'] == 0 ? '.0' : '.cmt' . $row['id_last_cmt']) . '#new')) . '" ' . ($row['work_comments'] == 0 ? '' : 'rel="nofollow"') . '>' . $row['work_title'] . '</a>'
),
'is_locked' => !empty($row['is_locked']),
'is_posted_in' => false,
'is_watched' => false,
'icon' => $row['id_genre'],
//'icon_url' => $settings[$context['icon_sources'][$row['first_icon']]] . '/post/' . $row['first_icon'] . '.png',
'title' => $row['work_title'],
'new' => $row['new_from'] <= $row['id_cmt_modified'],
'new_from' => $row['new_from'],
'newtime' => $row['new_from'],
'new_href' => $scripturl . '?work=' . $row['id_work'] . '.cmt' . $row['new_from'] . '#new',
'pages' => $pages,
'comments' => comma_format($row['work_comments']),
'views' => comma_format($row['work_views']),
);
}
$smcFunc['db_free_result']($result);

// Fix the sequence of topics if they were retrieved in the wrong order. (for speed reasons...)
if ($fake_ascending)
$context['works'] = array_reverse($context['works'], true);
}

// If there are children, but no topics and no ability to post topics...
$context['no_topic_listing'] = !empty($context['types']) && empty($context['works']);

// Build the message index button array.
$context['normal_buttons'] = array(
'new_topic' => array('test' => 'can_post_new', 'text' => 'new_topic', 'image' => 'new_topic.png', 'lang' => true, 'url' => $scripturl . '?action=post;type=' . $context['current_type'] . '.0', 'active' => true),
);

// Allow adding new buttons easily.
// Note: $context['normal_buttons'] is added for backward compatibility with 2.0, but is deprecated and should not be used
call_integration_hook('integrate_messageindex_buttons', array(&$context['normal_buttons']));

// Javascript for inline editing.
loadJavascriptFile('topic.js', array('default_theme' => true, 'defer' => false), 'smf_topic');
}
Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

Jade Elizabeth

Once proud Documentation Writer and Help Squad Leader | Check out my new adult coloring career: Color With Jade/Patreon.

Advertisement: