Post to SMF Forum via PHP

Started by KGrimes, January 06, 2016, 10:46:48 PM

Previous topic - Next topic

KGrimes

Hello, I am building a CMS that supports a website which also contains an SMF forum (2.0.11). One of the modules in the CMS involves a "report" that tracks attendance. That data is queried to tables outside of smf, but in the same database. In addition to what it does now, I would also like for a post to be made in a specific board on the SMF forum containing the formatted content. As all of the posts are contained by the database, surely this is possible, but it seems there is more to it than a single row in a table.

To put it in the simplest code possible, below is what I want to happen when I click Submit on my page.


$title = "2015-03-04 - Attendance";
$author = "KGrimes";
$body = "Attendance was good.";

$SQL = "INSERT INTO smf_some_table (title, author, body) VALUES ($title, $author, $body)";
$result = mysqli_query($db_handle, $SQL);


Having dug through the smf DB tables and the post() and post2() functions, it seems there is more than one table involved when a post is made. Has anyone outlined this before?

I've looked into solutions such as the Custom Form Mod, but these forms and templates are not what I am looking for. I already have the data inputted and POST'ed to variables, I just need the right table(s) to INSERT it into so that it appears on the forum.

Thank you in advance for any help!

Kindred

Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

margarett

Se forem conduzir, não bebam. Se forem beber... CHAMEM-ME!!!! :D

QuoteOver 90% of all computer problems can be traced back to the interface between the keyboard and the chair

KGrimes

Thanks for the reply, hadn't found either of those (but also never thought to look for an API). Before I dive in, should I be going for one or the other? The second option looks like it has nothing to do with the API, which is my preference, as long as it does its job (makes a post).

Kindred

well, the API is fully functioned... but you probably don't need it. The post highlighted by margarett is probably your best, simplest choice
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

KGrimes

I get the idea, but I am concerned about the variables. I assume the "optional" vs "necessary" definitions are indicated by whether the if statement is present else empty. But how do I know the format of these? For instance, is $board the id of the board? Name? Something else?


//SMF Post function
require 'Subs-Post.php';

// Collect all parameters for the creation or modification of a post.
$msgOptions = array(
'id' => empty($_REQUEST['msg']) ? 0 : (int) $_REQUEST['msg'],
'subject' => $_POST['subject'],
'body' => $_POST['message'],
'icon' => preg_replace('~[\./\\\\*:"\'<>]~', '', $_POST['icon']),
'smileys_enabled' => !isset($_POST['ns']),
'attachments' => empty($attachIDs) ? array() : $attachIDs,
'approved' => $becomesApproved,
);
$topicOptions = array(
'id' => empty($topic) ? 0 : $topic,
'board' => $board,
'poll' => isset($_REQUEST['poll']) ? $id_poll : null,
'lock_mode' => isset($_POST['lock']) ? (int) $_POST['lock'] : null,
'sticky_mode' => isset($_POST['sticky']) && !empty($modSettings['enableStickyTopics']) ? (int) $_POST['sticky'] : null,
'mark_as_read' => true,
'is_approved' => !$modSettings['postmod_active'] || empty($topic) || !empty($board_info['cur_topic_approved']),
);
$posterOptions = array(
'id' => $user_info['id'],
'name' => $_POST['guestname'],
'email' => $_POST['email'],
'update_post_count' => !$user_info['is_guest'] && !isset($_REQUEST['msg']) && $board_info['posts_count'],
);

//Excute SMF post
createPost(&$msgOptions, &$topicOptions, &$posterOptions);


Thanks again.

Edit:
Just found the page that discusses the function and every component of each array, very cool. Will reply if I have a further question or when it's working. Thanks!

http://support.simplemachines.org/function_db/index.php?action=view_function;id=323

KGrimes

#6

//Define variables
//msgOptions
$smf_subject = "Name Squad Drill Report Date TEST";

//Handle & escape
$smf_subject = htmlspecialchars($smf_subject);
$smf_subject = quote_smart($smf_subject, $db_handle);

$smf_body = "This is a test.";

//Handle & escape
$smf_body = htmlspecialchars($smf_body);
$smf_body = quote_smart($smf_body, $db_handle);

//topicOptions
$smf_board = 54; //Alpha Squad, need to make if/else for both

//posterOptions
$smf_id = 6; //Admin [3rd ID]

//SMF Post function
require 'Subs-Post.php';
//createPost($msgOptions, $topicOptions, $posterOptions);
// Create a post, either as new topic (id_topic = 0) or in an existing one.
// The input parameters of this function assume:
// - Strings have been escaped.
// - Integers have been cast to integer.
// - Mandatory parameters are set.

// Collect all parameters for the creation or modification of a post.
$msgOptions = array(
'subject' => $smf_subject,
'body' => $smf_body,
//'smileys_enabled' => !isset($_POST['ns']),
);
$topicOptions = array(
//'id' => empty($topic) ? 0 : $topic,
'board' => $smf_board,
'mark_as_read' => true,
);
$posterOptions = array(
'id' => $smf_id,
);

//Execute SMF post
createPost($msgOptions, $topicOptions, $posterOptions);


Fatal error: Function name must be a string in (my dir) on line 1770


// If nothing was filled in as name/e-mail address, try the member table.
if (!isset($posterOptions['name']) || $posterOptions['name'] == '' || (empty($posterOptions['email']) && !empty($posterOptions['id'])))
{
if (empty($posterOptions['id']))
{
$posterOptions['id'] = 0;
$posterOptions['name'] = $txt['guest_title'];
$posterOptions['email'] = '';
}
elseif ($posterOptions['id'] != $user_info['id'])
{
$request = $smcFunc['db_query']('', '   ////THIS IS LINE 1770
SELECT member_name, email_address
FROM {db_prefix}members
WHERE id_member = {int:id_member}
LIMIT 1',
array(
'id_member' => $posterOptions['id'],
)
);


The id is defined as an integer and an existing id (it's my own account). However, it is moving into the if/then as if the id did not exist. I've tried multiple id's, same thing. I've also tried redefining $posterOptions['name'] as "tester" to ensure it is a string but still no joy. Any idea what is going on here? Let me know if you need any more info. Thanks.

Edit: I now see that it isn't saying function, name, it is saying "function name", referring specifically to line 1770. But I haven't touched that, though I'm about to. Why is this happening?

Thanks again

Edit2:

echo is_null($smcFunc['db_query']); //returns 1 (true)


Given that, I guess my issue is that I need something else included to make sure that query data is present. Ideas...?

KGrimes

Below is where I'm at


//Define variables
//msgOptions
$smf_subject = "Name Squad Drill Report Date TEST";

//Handle & escape
$smf_subject = htmlspecialchars($smf_subject);
$smf_subject = quote_smart($smf_subject, $db_handle);

$smf_body = "This is a test.";

//Handle & escape
$smf_body = htmlspecialchars($smf_body);
$smf_body = quote_smart($smf_body, $db_handle);

//topicOptions
$smf_board = 54; //Alpha Squad, need to make if/else for both

//posterOptions
$smf_id = 6; //Admin [3rd ID]

//SMF Post function
require 'Subs-Db-mysql.php';

$db_server = '';
$db_name = '';
$db_user = '';
$db_passwd = '';
$db_prefix = '';
$db_persist = 0; //These variables were copied verbatim from settings.php, and I confirm they work there. Cleared for public view.

$db_connection = smf_db_initiate($db_server, $db_name, $db_user, $db_passwd, $db_prefix, array('persist' => $db_persist, 'dont_select_db' => SMF == 'SSI'));

require 'Subs-Post.php';
//createPost($msgOptions, $topicOptions, $posterOptions);
// Create a post, either as new topic (id_topic = 0) or in an existing one.
// The input parameters of this function assume:
// - Strings have been escaped.
// - Integers have been cast to integer.
// - Mandatory parameters are set.

// Collect all parameters for the creation or modification of a post.
$msgOptions = array(
'subject' => $smf_subject,
'body' => $smf_body,
//'smileys_enabled' => !isset($_POST['ns']),
);
$topicOptions = array(
//'id' => empty($topic) ? 0 : $topic,
'board' => $smf_board,
'mark_as_read' => true,
);
$posterOptions = array(
'id' => $smf_id,
);

//Excute SMF post
createPost($msgOptions, $topicOptions, $posterOptions);


However, I am getting fatal errors. The first is sprung on line 71 of Subs-Db-mysql.php, the second is on 104 of that same file (when the first is commented out). There error is because the fatal error function is undefined, but nonetheless it means there was a fatal error.


// Select the database, unless told not to
if (empty($db_options['dont_select_db']) && !@mysql_select_db($db_name, $connection) && empty($db_options['non_fatal']))
db_fatal_error();  ////FIRST ERROR IS SPRUNG HERE

// This makes it possible to have SMF automatically change the sql_mode and autocommit if needed.
if (isset($mysql_set_mode) && $mysql_set_mode === true)
$smcFunc['db_query']('', 'SET sql_mode = \'\', AUTOCOMMIT = 1',
array(),
false
);

return $connection;
}

// Extend the database functionality.
function db_extend($type = 'extra')
{
global $sourcedir, $db_type;

require_once($sourcedir . '/Db' . strtoupper($type[0]) . substr($type, 1) . '-' . $db_type . '.php');
$initFunc = 'db_' . $type . '_init';
$initFunc();
}

// Fix up the prefix so it doesn't require the database to be selected.
function db_fix_prefix(&$db_prefix, $db_name)
{
$db_prefix = is_numeric(substr($db_prefix, 0, 1)) ? $db_name . '.' . $db_prefix : '`' . $db_name . '`.' . $db_prefix;
}

function smf_db_replacement__callback($matches)
{
global $db_callback, $user_info, $db_prefix;

list ($values, $connection) = $db_callback;

if (!is_resource($connection))
db_fatal_error();  /////SECOND ERROR IS SPRUNG HERE

if ($matches[1] === 'db_prefix')
return $db_prefix;


Thanks again for any help.

Suki

You don't need to initiate a db connection, SMF does that for you.

Include SMF's SSI.php file in your php file, use the absolute path to where SSI.php is located, after that, almost everything in SMF its at your disposition.

createPost is located on Sources/Subs-Posts.php if memory serve me right, so just include that file before calling that function:

require_once('path/to/smf/Sources/Subs-Posts.php');
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

Illori

Quote from: Suki on January 07, 2016, 07:38:07 PM
require_once('path/to/smf/Sources/Subs-Posts.php');

the file is Subs-Post.php

KGrimes

Ah, we were on different wave lengths. I was stripping SMF apart going include to include, function to function to be as minimalist as possible in extracting the createPost function. Your method was of course much cleaner, and got the job done first try. Below is the code I'm using.


//Define variables
//msgOptions
$smf_subject = "Name Squad Drill Report Date TEST";

//Handle & escape
$smf_subject = htmlspecialchars($smf_subject);
$smf_subject = quote_smart($smf_subject, $db_handle);

$smf_body = "This is a test.";

//Handle & escape
$smf_body = htmlspecialchars($smf_body);
$smf_body = quote_smart($smf_body, $db_handle);

//topicOptions
$smf_board = 54; //Alpha Squad, need to make if/else for both

//posterOptions
$smf_id = 6; //Admin [3rd ID]

//SMF Post function
require_once('../../forums/SSI.php');
require_once('../../forums/Sources/Subs-Post.php');

//createPost($msgOptions, $topicOptions, $posterOptions);
// Create a post, either as new topic (id_topic = 0) or in an existing one.
// The input parameters of this function assume:
// - Strings have been escaped.
// - Integers have been cast to integer.
// - Mandatory parameters are set.

// Collect all parameters for the creation or modification of a post.
$msgOptions = array(
'subject' => $smf_subject,
'body' => $smf_body,
//'smileys_enabled' => !isset($_POST['ns']),
);
$topicOptions = array(
//'id' => empty($topic) ? 0 : $topic,
'board' => $smf_board,
'mark_as_read' => true,
);
$posterOptions = array(
'id' => $smf_id,
);

//Execute SMF post
createPost($msgOptions, $topicOptions, $posterOptions);


Still some items to play with, including making a reply, but I see that just involves defining a topic id. Is there an SMF way to do this? Right now my plan is create the topic then query that table for the latest id and save that on one of my tables for future reference regarding that specific report (When the report is edited, I want a reply posted in the same topic). Any ideas would be appreciated. Thanks again for all the help, I look forward to digging in a little deeper with SMF.

Kindred

honestly, it sounds like you are duplicating the functionality of SimpleDesk...
Слaва
Украинi

Please do not PM, IM or Email me with support questions.  You will get better and faster responses in the support boards.  Thank you.

"Loki is not evil, although he is certainly not a force for good. Loki is... complicated."

Suki

Once createPost() is called, $topicOptions['id'] will contain the topic ID you just created so if you want to create a reply to the topic you just created call createPost once again and use $topicOptions['id'].

Just be careful, you can't reuse the same vars (unless you really want to), $topicOptions, $posterOptions, $msgOptions since those were used in the first createPost call, you either have to unset them, overwrite them or use new ones.
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

KGrimes

Thanks for the reply Suki. Fortunately these actions are completely independent of each other, located on different pages. I went a step further and actually used modifyPost instead of making a reply (the only reason I would do reply was because I thought modifying would be tough, but if anything it is easier!).

Thank y'all for the help!

Advertisement: