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!
Source: http://www.simplemachines.org/community/index.php?topic=542521.0
Code where you want to create post:
//Define variables
//msgOptions
$smf_subject = "Test Title";
//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; //Any board id, found in URL
//posterOptions
$smf_id = 6; //any id, this is found as ID in memberlist
//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);
This will create the simplest of posts with title and body defined by you, along with location and who the author is. More parameters can be found in the SMF functions database for createPost. The SSI and Subs-Post.php includes must be the original directly, copying them over doesn't do the trick.
Related
I want to override the item listing template file core/themes/classy/templates/dataset/item-list.html.twig for listing the fields field_slider_images as well as field_blog_tags respectively of their's multiple values of the field.
I have selected "Unordered List" in the view.
Please do check the attached image.
I have created following files :
item-list--field-blog-tags.html.twig
item-list--field-slider-images.html.twig
But, this is not rendered for the listing of the fields.
When I have created item-list.html.twig then only it will access.
However, both fields have different data to style and I am not able to get the current field name which is loading it's data in item-list.html.twig.
Had a brief look at this and it doesn't seem that 'item-list' to have suggestions, which is quite unfortunate.
In this situation there are two options:
Create your own suggestion which would accomplish exactly what you need.
You'll have to do something like this:
/
/*add new variable to theme with suggestion name*/
function hook_theme_registry_alter(&$theme_registry) {
$theme_registry['item_list']['variables']['suggestion'] = '';
}
//send a value to newly added variable to use it build the suggestion
function hook_ENTITY_TYPE_view(array &$build, $entity, $display, $view_mode) {
//add condition here if field exists or whatever, do the same for other field
$build['field_slider_images']['#suggestion'] = 'field_slider_images';
}
//use newly added variable to build suggestion
function hook_theme_suggestions_THEME_HOOK(array $variables) {//THEME_HOOK=item_list
$suggestions = array();
if(isset($variables['suggestion'])){
$suggestions[] = 'item_list__' . $variables['suggestion'];
}
return $suggestions;
}
Now you should be able to use item-list--field-slider-images.html.twig
Second option is to do what others in core did: use a new theme
function hook_ENTITY_TYPE_view(array &$build, $entity, $display, $view_mode) {
//add condition here if field exists or whatever, do the same for other field
$build['field_slider_images']['#theme'] = array(
'item_list',
'item_list__field_slider_images',
);
}
I'm running into some n+1 performance issues when iterating over a collection of ContentItems of a custom Type that I created solely through migrations.
ContentDefinitionManager.AlterPartDefinition("MyType", part => part
.WithField("MyField", field => field
...
)
);
ContentDefinitionManager.AlterTypeDefinition("MyType", type => type
.WithPart("MyType")
);
Every time I access a field of this part a new query is performed. I can use QueryHints to avoid this for the predefined parts
var myItems = _orchardServices.ContentManager.Query().ForType("MyType")
.WithQueryHints(new QueryHints().ExpandParts<LocalizationPart()
...
);
but can I do this for the ContentPart of my custom type too? This does not seem to work:
var myItems = _orchardServices.ContentManager.Query().ForType("MyType")
.WithQueryHints(new QueryHints().ExpandParts<ContentPart>()
...
);
How can I tell Orchard to just get everything in one go? I'd prefer to be able to do this without writing my own HQL or directly addressing the repositories.
Example:
var myItems = _orchardServices.ContentManager.Query().ForType("MyType");
#foreach(var item in myItems.Take(100)) {
foreach(var term in item.Content.MyItem.MyTaxonomyField.Terms) {
// Executes 100 queries
<div>#term.Name</div>
}
}
TaxonomyField doesn't store ids and using the TaxonomyService inside of the loop wouldn't improve performance. Right now, to work around this, I fetch all TermContentItems.Where(x => myItems.Select(i => i.Id).Contains(TermPartRecord.Id)) from the repository outside of the loop as well as a list of all the terms of the Taxonomy that the field is using. Then inside the loop:
var allTermsInThisField = termContentItems.Where(tci => tci.TermsPartRecord.Id == c.Id)
.Select(tci => terms.Where(t => t.Id == tci.TermRecord.Id).Single()).ToList()
I'm not a very experienced programmer but this was the only way I could see how to do this without digging into HQL and it seems overly complicated for my purposes. Can Orchard do this in less steps?
Given code like this:
IContent part = ....; // some part object like IUser
var fieldValues = part.ContentItem.Parts
.SelectMany(p => p.Fields)
.Where(f => f.Name == "some field name");
Which table are the field values stored in, or are they stored somewhere else?
I'm using SQL Server as the back-end database for Orchard. I see the fields are defined in table Settings_ContentPartFieldDefinitionRecord but I don't know where the actual values are stored.
Orchard_Framework_ContentItemVersionRecord
Check out this blog post by the lead developer on Orchard, Sebastien Ros, who talks a little about the database structure. http://sebastienros.com/understanding-orchard-s-database
Guess my problem is closely related to this one : Snippet duplicates content when used multiple times on page
The elements of my problem are the following ...
$modx->loadedResources : an (empty) array registered in the main $modx object via a snippet on page load. The array holds resource id's of the resources fetched from the DB randomly, so the same resource isn't shown twice on the same page.
loadRandomResource : a snippet using XPDO-style querying to load a random resource from the DB. It uses $modx->parseChunk() to fill the placeholders in the chunk with the resource data. With each call, it appends the id of the fetched resource being fetched to the $modx->loadResources array.
I used some debugging to check if the resource id's were properly being stored in my array, each time I fetch a new random resource, which happens to be the case. I then checked if the db returns different results, each time I call the loadRandomResource snippet, and it does. I can also confirm that it doesn't return duplicate results (I exclude the already loaded resource ID's in my XPDO query).
However, when calling the snippet at 3 various locations throughout my page template, all 3 snippet calls render the same resource, which is weird, since my debug shows that unique data is being loaded from the DB, and being sent to the chunk for rendering.
Please find below both the snippet code, as well as the chunk mark-up.
Does anyone have any ideas? Any help is much appreciated!
loadRandomResource snippet
$criteria = $modx->newQuery('modResource');
$criteria->select(array('id','pagetitle'));
$criteria->sortby('RAND()');
$criteria->limit(1);
$whereOptions = array(
'parent' => 2,
'deleted' => false,
'hidemenu' => false,
'published' => true
);
if (!empty($modx->loadedResources)) {
$whereOptions['id:NOT IN'] = $modx->loadedResources;
}
$criteria->where($whereOptions);
$resources = $modx->getCollection('modResource', $criteria);
$output = '';
foreach ($resources as $resource) {
$fields = $resource->toArray();
$fields['tv.tvPersonalPicture'] = $resource->getTVValue('tvPersonalPicture');
$fields['tv.tvJobTitle'] = $resource->getTVValue('tvJobTitle');
$output .= $modx->parseChunk('cnkTeamListItem', $fields);
$modx->loadedResources[] = $fields['id'];
}
return $output;
cnkTeamListItem chunk
<div>
<img src="[[+tv.tvPersonalPicture]]" alt="[[+pagetitle]]" />
<h2>[[+pagetitle]]<br /><span>[[+tv.tvJobTitle]]</span></h2>
</div>
I found the answer myself, solution is a bit odd though ...
I was calling my custom snippet 3 times in my template, uncached. Each call though exactly looked the same ...
[[!loadRandomResource? &type='teammember']]
Even though I had the exclamation mark in place, still ModX was caching the call, within the same page request.
So when I added a random unique value to each of the 3 calls, the issue was solved.
Call 1 : [[!loadRandomResource? &type='teammember' &unique='123465']]
Call 2 : [[!loadRandomResource? &type='teammember' &unique='987654']]
Call 1 : [[!loadRandomResource? &type='teammember' &unique='666666']]
Don't know if this is a bug or a feature, but I thought that the exclamation mark prevented caching, both across different pageviews, as well as within the same page view. Anyhow, thx for helping.
I use this code for rendering chunks in snippents:
<?php
// get chunk or template
$tplRow = $modx->getOption('tplRow', $scriptProperties, '');
// get template
if (substr($tplRow, 0, 6) == "#CODE:") {
$tplRow = substr($tplRow, 6);
} elseif ($chunk = $modx->getObject('modChunk', array('name' => $tplRow), true)) {
$tplRow = $chunk->getContent();
} else {
$tplRow = false;
}
// render template
$field = array(); // your fields
if ($tplRow) {
$chunk = $modx->newObject('modChunk');
$chunk->setCacheable(false);
$chunk->setContent($tplRow);
$output[]= $chunk->process($fields);
} else {
$output[]= '<pre>' . print_r($fields, 1) . '</pre>';
}
You do realize you could have done this with getResources, don't you?
http://rtfm.modx.com/display/ADDON/getResources
&sortby=`RAND()`&limit=`1`
i have a page tweety which contains a single form where a user enters a word in a textbox and in on pressing search the tweets corresponding to that word are displayed.
I want to use hook_nodeapi to add these tweets but i want those things only on a specific url not all the page(or any node type).
I ll use hook_menu to make that page and display the form for the search. What should i do after that. I knw the twiiter api to fetch the tweets so that is not a issue.
I think what you're attempting to do is have the tweets load on a predetermined page by passing the posted information to the page, is that correct?
There's a couple ways I think you could accomplish this - easiest, and not requiring any complex ahah scripting would be to take the word they enter and generate a path which you could then use to make the page in question.
Make a menu Item:
function mymodule_menu() {
$items = array();
$items['mymodule/tweets/%'] = array(
'title' => t('Tweets about' . check_plain(array(2))),
'page callback' => 'mymodule_tweet_display',
'page arguments' => array(2) // This is the 3rd argument in the path, the %
);
}
In your form, you'll need to send the user to this path so add to your hook_submit function:
$tweet_topic = $form_state['values']['your-field-name-here'];
drupal_goto('mymodule/tweets/' . $tweet_topic);
Now add your page module, this is where you can use the twitter api:
function mymodule_tweet_display($tweet_topic) {
$tweet_topic = check_plain($tweet_topic);
// Use this variable in your Twitter API call
// ...
// Make sure you assign your display content to the page by returning a variable
return $page;
}