I am a newbie but this may be useful, assuming you haveread the "build a 3rd part component with custom DB" tutorial.
It’s a draft snippet called "rafentries" that allows logged users to post entries ( title, message, skills, price, delay, ispublic). 3 context are handled ( "web", "en" and "de" ) storing entries from each context in a separate table.
raf_entries_web
raf_entries_en
raf_entries_de
The site declines in
http://mysite.localhost/
http://en.mysite.localhost/
http://de.mysite.localhost/
Let’s define our 3 tables in rafentries.mysql.schema.xml
<?xml version="1.0" encoding="UTF-8"?>
<model package="rafentries" baseClass="xPDOObject" platform="mysql" defaultEngine="MyISAM" phpdoc-package="rafentries" phpdoc-subpackage="model">
<object class="rafEntries_web" table="raf_entries_web" extends="xPDOSimpleObject">
<field key="usrid" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="false" />
<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
<field key="alias" dbtype="varchar" precision="255" phptype="string" null="false" index="index" />
<field key="entry" dbtype="mediumtext" phptype="string" null="false" />
<field key="skills" dbtype="varchar" precision="255" phptype="string" null="true" />
<field key="delay" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="price" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="status" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="public" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="ip" dbtype="varchar" precision="255" phptype="string" null="true" />
<field key="editedon" dbtype="datetime" phptype="datetime" null="true" />
<field key="createdon" dbtype="datetime" phptype="datetime" null="true" />
</object>
<object class="rafEntries_en" table="raf_entries_en" extends="xPDOSimpleObject">
<field key="usrid" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="false" />
<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
<field key="alias" dbtype="varchar" precision="255" phptype="string" null="false" index="index" />
<field key="entry" dbtype="mediumtext" phptype="string" null="false" />
<field key="skills" dbtype="varchar" precision="255" phptype="string" null="true" />
<field key="delay" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="price" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="status" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="public" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="ip" dbtype="varchar" precision="255" phptype="string" null="true" />
<field key="editedon" dbtype="datetime" phptype="datetime" null="true" />
<field key="createdon" dbtype="datetime" phptype="datetime" null="true" />
</object>
<object class="rafEntries_de" table="raf_entries_de" extends="xPDOSimpleObject">
<field key="usrid" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="false" />
<field key="title" dbtype="varchar" precision="255" phptype="string" null="false" />
<field key="alias" dbtype="varchar" precision="255" phptype="string" null="false" index="index" />
<field key="entry" dbtype="mediumtext" phptype="string" null="false" />
<field key="skills" dbtype="varchar" precision="255" phptype="string" null="true" />
<field key="delay" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="price" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="status" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="public" dbtype="int" precision="1" attributes="unsigned" phptype="integer" null="true" />
<field key="ip" dbtype="varchar" precision="255" phptype="string" null="true" />
<field key="editedon" dbtype="datetime" phptype="datetime" null="true" />
<field key="createdon" dbtype="datetime" phptype="datetime" null="true" />
</object>
</model>
Now after building, comes the snippet /core/components/rafentries/snippet.rafentries.php
<?php
/**
* @package rafentries
*/
$publishedByDefault = 0;
$alias = $_GET['alias'];// check here if alias exists (and if usrid is ok if edit)
if ( $service == 'viewentries' && $alias != '' ) {
$service='viewentry';
}
$title = $_POST['title'];
$entryId = $_POST['entryId'];
$entry = $_POST['entry'];
$skill1 = $_POST['skill1'];
$delay = ( int ) $_POST['delay'];
$price = ( int ) $_POST['price'];
$public = ( int ) $_POST['public'];
$status = array ( 'unpublishentry'=>2, 'closeentry'=>3, 'removeentry'=>4 );
$contexts = array ( 'mysite'=>'web', 'en'=>'en', 'de'=>'de' );
$tmp = explode ( '.', $_SERVER['HTTP_HOST'] );
$context = $contexts[ $tmp[ 0 ] ];
$userId = $modx->getLoginUserID($context);
$base_path = !empty($base_path) ? $base_path : $modx->getOption('core_path').'/www/mysite/core/components/rafentries/';
$modx->addPackage( 'rafentries',$base_path.'model/' );
if ( $service == 'newentry' && !empty( $_POST ) ) {
if ( $title != '' && $entry != '' ) {
$storeEntry = $modx -> newObject ( 'rafEntries_'.$context );
$storeEntry->fromArray(array(
'usrid' => $userId,
'title' => $title,
'alias' => makeAlias($title),
'entry' => $entry,
'delay' => $delay,
'price' => $price,
'skills' => $skill1,
'status' => $publishedByDefault,
'public' => $public,
'ip' => get_ip(),
'createdon' => time(),
));
$storeEntry->save();
$url = $modx->makeUrl($successRedirectPage,'','','full');
$modx->sendRedirect($url,0,REDIRECT_META);
}
}
if ( $service == 'viewentries' || $service=='viewentry' || $service=='viewmyentries' ) {
$sortie = array();
if ( $service=='viewmyentries') {
$entries = $modx->getCollection('rafEntries_'.$context, array ( 'usrid' => $userId,));
}
elseif ( $service=='viewentries') {
$entries = $modx->getCollection('rafEntries_'.$context);
}
elseif ( $service=='viewentry') {
$entries = $modx->getCollection('rafEntries_'.$context,array ('alias' => $alias,));
}
foreach ($entries as $entry) {
if ( ( $service=='viewentry' && $alias == $entry->get( 'alias' ) ) || $service!='viewentry' ) {
$properties = $entry->toArray();
$sortie[] = $modx->getChunk('tplEntries', $properties);
$modx->setPlaceholders(array(
'id' => $entry->get('id'),
'usrid' => $entry->get('usrid'),
'title' => $entry->get('title'),
'alias' => $entry->get('alias'),
'entry' => $entry->get('entry'),
'skills' => $entry->get('skills'),
'price' => $entry->get('price'),
'delay' => $entry->get('delay'),
'status' => $entry->get('status'),
'public' => $entry->get('public'),
'ip' => $entry->get('ip'),
'editedon' => $entry->get('editedon'),
'createdon' => $entry->get('createdon'),
)
,'entry.');
}
}
$output.=implode("\n", $sortie);
}
if ( $service == 'editentry') {
if ( $userId>0) {
if ( !empty ( $_POST ) ) {
if ( $title!='' && $entry!='' ) {
$storeEntry = $modx->getObject('rafEntries_'.$context,array ('alias' => $alias, 'usrid'=>$userId, ));// && usridd=ok a tester
$storeEntry->fromArray(array(
'title' => $title,
'entry' => $entry,
'delay' => $delay,
'price' => $price,
'skills' => $skill1,
'editedon' => time(),
));
$storeEntry->save();
$url = $modx->makeUrl($successRedirectPage,'','','full');
$modx->sendRedirect($url,0,REDIRECT_META);
}
}
$entry = $modx->getObject('rafEntries_'.$context,array ('alias' => $alias, 'usrid'=>$userId, ));
$properties = $entry->toArray();
$output = $modx->getChunk('tplEditEntry', $properties);
$modx->setPlaceholders(array(
'id' => $entry->get('id'),
'title' => $entry->get('title'),
'alias' => $entry->get('alias'),
'entry' => $entry->get('entry'),
'skills' => $entry->get('skills'),
'price' => $entry->get('price'),
'delay' => $entry->get('delay'),
'status' => $entry->get('status'),
'public' => $entry->get('public'),
'editedon' => $entry->get('editedon'),
'createdon' => $entry->get('createdon'),
)
,'entry.');
}
}
if ( $service == 'unpublishentry' || $service == 'closeentry' || $service == 'removeentry') {
$entry = $modx->getObject('rafEntries_'.$context,array ('alias' => $alias, 'usrid'=>$userId, ));
$properties = $entry->toArray();
$sortie[] = $modx->getChunk('tplEntries', $properties);
$modx->setPlaceholders(array(
'id' => $entry->get('id'),
'usrid' => $entry->get('usrid'),
'title' => $entry->get('title'),
'alias' => $entry->get('alias'),
'entry' => $entry->get('entry'),
'skills' => $entry->get('skills'),
'price' => $entry->get('price'),
'delay' => $entry->get('delay'),
'status' => $entry->get('status'),
'public' => $entry->get('public'),
'ip' => $entry->get('ip'),
'editedon' => $entry->get('editedon'),
'createdon' => $entry->get('createdon'),
)
,'entry.');
if ( $userId == $entry->get('usrid')) {
if ( $alias == $entry->get('alias') ) {
$storeEntry = $modx->getObject('rafEntries_'.$context,array ('alias' => $alias, 'usrid'=>$userId, ));
$storeEntry->fromArray(array(
'status'=>$status[$service],
));
$storeEntry->save();
}
}
}
if ( $service == 'replyentry' ) {
if ( $userId>0) {
}
}
echo $output;
// change this later by using the modx stuff for autoalias generation
function makeAlias($url){
$url = no_accent($url);
$url = ereg_replace("[^a-z A-Z0-9-]*","",$url);
$url = ereg_replace("-{2,}","-",$url);
$url = ereg_replace(' ','-',$url);
$url = trim(strtolower($url));
$url = ltrim($url,'-');
$url = rtrim($url,'-');
return $url;
}
function no_accent($filename) {
$str = strtr(utf8_decode($filename),utf8_decode("ÀÁÂÃÄÅÇÑñÇçÈÉÊËÌÍÎÏÒÓÔÕÖØÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöøùúûüýÿ' "),
"AAAAAACNnCcEEEEIIIIOOOOOOUUUUYaaaaaaceeeeiiiiooooooouuuuyy--" );
return $str;
}
function get_ip() {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
elseif(isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
}
else {
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
Set up url rewriting ( i do this amateur with .htaccess, temporary solution )
RewriteRule ^yourpath/([0-9A-Za-z-]+)/$ yourpath/?alias=$1 [L,QSA]
The template tplEditEntry :
<form action="[[++site_url]][[~[[++page_modify_entry]]]][[+entry.alias]]/" method="post" name="entryForm" autocomplete="on" accept-charset="[[++modx_charset]]" enctype="multipart/form-data">
<fieldset>
<legend>[[%edit_entry]]</legend>
<label for="title"><span class="padLeft">[[%title]]</span>[[$arrow1]]
<input id="title" name= "title" type="text" value="[[+entry.title]]" /></label>
<label for="entry"><span class="padLeft">[[%entry]]</span>[[$arrow1]]
<textarea id="entry" name="entry">[[+entry.entry]]</textarea></label>
<label for="skill1"><span class="padLeft">[[%required_skills]]</span>[[$arrow1]]
<input id="skill1" name= "skill1" type="text" value="[[+entry.skills]]" /></label>
<label for="price"><span class="padLeft">[[%approx_price]] [[++currency]]</span>[[$arrow1]]
<input id="price" name= "price" type="text" value="[[+entry.price]]" /></label>
<label for="delay"><span class="padLeft">[[%deadline]]</span>[[$arrow1]]
<input id="delay" name= "delay" type="text" value="[[+entry.delay]]" /></label>
<button type="submit" name="newEntryBtn" value="[[%edit_entry]]">[[%edit_entry]]</button>
</fieldset>
</form>
And then the template tplEntries :
<li class="summary">
<ul>
<li>
<a href="[[++site_url]][[~[[++page_entries]]]][[+entry.alias]]/"><strong>[[+entry.title]]</strong></a></li>
<li>[[+entry.entry]]</strong>
</li>
[[!If? &operator=`NEQ` &operand=`` &subject=`[[+entry.createdon]]` &then=`<li><span>[[%createdon]]</span>[[$arrow1]][[+entry.createdon]]</li>`]]
[[!If? &operator=`NEQ` &operand=`` &subject=`[[+entry.editedon]]` &then=`<li><span>[[%editedon]]</span>[[$arrow1]][[+entry.editedon]]</li>`]]
[[!If? &operator=`NEQ` &operand=`` &subject=`[[+entry.skills]]` &then=`<li><span>[[%required_skills]]</span>[[$arrow1]][[+entry.skills]]</li>`]]
[[!If? &operator=`NEQ` &operand=`` &subject=`[[+entry.price]]` &then=`<li><span>[[%approx_price]]</span>[[$arrow1]][[+entry.price]] [[++currency]]</li>`]]
[[!If? &operator=`EQ` &operand=`1` &subject=`[[+entry.delay]]` &then=`<li><span>[[%deadline]]</span>[[$arrow1]][[+entry.delay]] [[++time_unit]]</li>`]]
[[!If? &operator=`GT` &operand=`1` &subject=`[[+entry.delay]]` &then=`<li><span>[[%deadline]]</span>[[$arrow1]][[+entry.delay]] [[++time_unit_plural]]</li>`]]
[[If? &operator=`EQ` &operand=`advertisers` &subject=`[[!+mf.group]]` &then=`[[$advEntryActions]]`]]
[[If? &operator=`EQ` &operand=`competitors` &subject=`[[!+mf.group]]` &then=`[[$cmpEntryActions]]`]]
[[If? &operator=`EQ` &operand=`(anonymous)` &subject=`[[+modx.user.username]]` &then=`[[%login_or_register_to_reply]]`]]
</ul>
</li>
Form to add entry :
<form action="[[++site_url]][[~[[*id]]]]" method="post" name="entryForm" autocomplete="on" accept-charset="[[++modx_charset]]" enctype="multipart/form-data">
<fieldset>
<legend>[[$checkbox1]][[%required_informations]]</legend>
<label for="title"><span class="padLeft">[[%entry_title]]</span>[[$arrow1]]
<input id="title" name= "title" type="text"></label>
<label for="entry"><span class="padLeft">[[%your_entry]]</span>[[$arrow1]]
<textarea id="entry" name="entry"></textarea></label>
<legend>[[$checkbox1]][[%optional_informations]]</legend>
<label for="skill1"><span class="padLeft">[[%required_skills]]</span>[[$arrow1]]
<input id="skill1" name="skill1" type="text" /></label>
<label for="delay"><span class="padLeft">[[%deadline]]</span>[[$arrow1]]
<input id="delay" name="delay" type="number" min="1" max="365" /></label>
<label for="price"><span class="padLeft">[[%approx_price]]</span>[[$arrow1]]
<input id="price" name="price" type="number" min="[[++min_price_allowed]]" max="[[++max_price_allowed]]" /></label>
</fieldset>
<button type="submit" name="newEntryBtn" value="[[%submit_new_entry]]">[[%submit_new_entry]]</button>
</form>
Usage ( call on the same page, just befor the previous form ) :
[[rafEntries? &service=`service`]]
service values => newentry, viewentry, viewentries, viewmyentries, unpublishentry, closeentry, removeentry