Kamis, 20 Agustus 2020

Joomla Component - Important Scripts

Some important scripts to simplify joomla component development.

1. Refer function from other models.

Calling from a model, referring to function in other model. For example, referring to "Home" model, in component called "CCauth", function called "get_things" with the rest function parameters.

$results = $this->getInstance('Home', 'CCauthModel')-> get_things(array('alias', 'name'), 'ccempl', 'status', 1);

2. Important function:  The function compares a value against array of values. Return the compared ("$data") value if match or return default value if not found. In below sample, default value is empty.
  
public function validateCompare($data="", $validData = array())
{
//This function to compare a string against valid data in arrays.
$data = $this->sanitizeInput($data);
//set default first
$result = "";// set default result to first valid data if not found
//compare, if found override result
foreach ($validData as $testdata){
if($testdata == $data){
$result = $data; //override result
}
}
return $result;
}

3. To get column/array with optional where and sort:
public function getColumn($select, $table, $where="", $ins="", $ordering="", $by="") {
// This function is to get eligible items as arrays.
// Apply restrictions accordingly.
// No need to apply ordering in the query
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName($select)); //change field
$query->from($db->quoteName($table)); // change when change table
// here is the matching criteria:  
if($where!=""){
$query->where($db->quoteName($where) . ' = '. $db->quote($ins));
}
if($ordering!=""){
$query->order($db->quote($ordering.$by));
}
$db->setQuery($query);
$results = $db->loadColumn();
return $results;
}

Jumat, 04 Januari 2019

Joomla 3.x Import CSV file to Joomla Database

Below is the codes inserted in the controller, with function called "import_from_file".

function import_from_file()
{
$validate = 1;//default success -- meanwhile dont do anything
$message = JText::_('COM_TESTDATA_SUCCESSFUL_POST');//default message - cc change component

//validation process below is working 28/12

$columns = array();
$values = array();
$row = 1;
if (($handle = fopen("tmp/dataw.csv", "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data); //$num = number of columns or fields
if($row == 1){ //as header, then array per item
for ($c=0; $c < $num; $c++) { // $cs = field in a record
$disp = $data[$c]; //just to make some data displayed.
array_push($columns, $data[$c]); // first row is treated as headers
}
$row++; // go to next record
}
else{
$imploded ="'". implode("','", $data) ."'";// patch a bit, if no '' then sometimes error in joomla
array_push($values, $imploded);
}
}
}
fclose($handle);


$arrlength = count($columns);
for($x = 0; $x < $arrlength; $x++) {
echo $columns[$x];
echo "<br>";
}


if($validate == 1){

try {
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->insert($db->quoteName('#__testdata'));
$query->columns($columns); //set columns headers
$query->values($values); // insert the values here.
$db->setQuery($query);
$db->query();
$message = 'Success!'; //need to work on this later.
echo $validate;
}
catch (Exception $e) {
$message = 'Caught exception: '.  $e->getMessage();
}
}


parent::display($cachable = false, $urlparams = false);
}

Senin, 31 Desember 2018

Joomla 3.x feature, display list of items from csv file

This feature can be used alone, to display file, or to integrate it with upload feature for review or  confirmation, before data is imported to database.

For the file to be displayed, I hardcode "tmp/datax.csv". You can change it to the file you wanna open, or selectable by user once you integrate it with other function.


these are the codes put in the controller:
function export_displaynow()
{


$validate = 1;//default success -- meanwhile dont do anything
$message = JText::_('COM_TESTDATA_SUCCESSFUL_POST');//default message
//validation process below is working 28/12
$db = JFactory::getDbo();
$query = $db->getQuery(true);

$row = 1;
if (($handle = fopen("tmp/datax.csv", "r")) !== FALSE) { // datax.csv to be customized.
echo '<table>';
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$num = count($data);
echo '<tr> <td>';
echo "<p> $num fields ind line $row: </p>";
$row++;
$disp = $data;
for ($c=0; $c < $num; $c++) {
echo '<td>';
echo $data[$c] . "<br />\n";
echo '</td>';
}
echo '</tr>';
}
echo '</table>';
fclose($handle);
}


return $disp;
$this->input->set('view', 'exportlist');

parent::display($cachable = false, $urlparams = false);
}

Joomla 3.x Upload File Feature

Completed the upload feature for joomla 3.x (tested in joomla 3.4).

I have not checked Joomla's recommended ways to do it, but somehow I mixed the scripts with common php codes.

Some validations applied here are extensions, file size, MIME types. Customize them according to your need.

In the layout form, insert this submit button.

<input type="file" name="file_upload"  />

<input type="submit" />
                         
  <input type="hidden" name="task" value="export_now" /> 
  <input type="hidden" name="option" value="com_testdata" />

  <?php echo JHtml::_('form.token'); ?>
</form>

Below the codes, which I put in the controller. It's bit messy but they work:

function export_now()
{
clearstatcache();
jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');
//$file = JFactory::getApplication()->input->get('file_upload');
if(!defined('DS')) define('DS', DIRECTORY_SEPARATOR);
if(!defined('DS')) define('DS', '/');
$fileName = basename($_FILES["file_upload"]["name"]);


//check the file extension is ok
$uploadedFileNameParts = explode('.',$fileName);
$uploadedFileExtension = array_pop($uploadedFileNameParts);

$validFileExts = explode(',', 'jpeg,jpg,png,gif,csv'); //change when needed

$extOk = false;

foreach($validFileExts as $key => $value)
{
if( preg_match("/$value/i", $uploadedFileExtension ) )
{
$extOk = true;
}
}

if ($extOk == false) 
{
echo JText::_( 'INVALID EXTENSION' );
        return;
}
//we are going to define what file extensions/MIMEs are ok, and only let these ones in (whitelisting), rather than try to scan for bad
//types, where we might miss one (whitelisting is always better than blacklisting) 
$okMIMETypes = 'image/jpeg,image/pjpeg,image/png,image/x-png,image/gif,text/csv';
$validFileTypes = explode(",", $okMIMETypes);

$uploadOk = 1; // default success validation

//if the temp file does not have a width or a height, or it has a non ok MIME, return
if( !$validFileTypes) 
{
$er = JText::_( 'INVALID FILETYPE' );
$uploadOk = 0;
}
$fileTemp = $_FILES["file_upload"]["tmp_name"];
$fileSize = $_FILES["file_upload"]["size"];
//lose any special characters in the filename
$fileName = preg_replace("/[^A-Za-z0-9]/i", "-", $fileName);

//always use constants when making file paths, to avoid the possibilty of remote file inclusion

$target_file = JPATH_SITE . DS . "tmp" . DS . $fileName;
// Check if file already exists

if (file_exists($target_file)) {
    $er = "Sorry, file already exists.";
    $uploadOk = 0;
}
// Check file size
if ($fileSize > 200000 || $fileSize <= 0 ) { //2kb
    $er = "Sorry, your file is too large : " . $fileSize;
    $uploadOk = 0;
}

if($uploadOk == 1)
{
if(!JFile::upload($fileTemp, $target_file)) 
{
echo JText::_( 'ERROR MOVING FILE' );
echo 'target file upload: '.$target_file.'<br/>';
return;
}
else
{
   // success, exit with code 0 for Mac users, otherwise they receive an IO Error
echo 'success <br/>';
echo 'target file upload: '.$target_file.'<br/>';
return;
}
}
else{
echo 'error, '. $er;
echo 'target file upload: '.$target_file.'<br/>';
return;
}
}


Rabu, 26 Desember 2018

Export Joomla Database Table to CSV

Completed new component module to export table to csv file for Joomla 3.x.

In the template file, put this as submit button to initiate the export.

My component is called "com_testdata", so adjust accordingly.
The task value is "export_now", which is later captured by the component controller.

<form action="index.php" method="post" name="myForm" id="myForm" onsubmit="return submitbutton();" >


<input type="submit" name="export" class="btn btn-success" value="Export to CSV"/>

  <input type="hidden" name="task" value="export_now" /> 
  <input type="hidden" name="option" value="com_testdata" />

  <?php echo JHtml::_('form.token'); ?>
</form>

This is how the component controllers, below the switch task. It is calling a function called export_now():

$task = $this->input->getCmd('view', 'display');
switch ($task){


case 'export_now':
export_now();
break;

This is the export_now() function:

function export_now()
{
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select($db->quoteName(array('id','message')));
$query->from($db->quoteName('#__testdata')); //change database
//validation
$query->where($db->quoteName('published') . ' = '. $db->quote('1'));
$query->where($db->quoteName('expired') . ' != '. $db->quote(null)); //article is not expired
$query->where($db->quoteName('expired') . ' > '. $db->quote(date('Y-m-d') ."\n")); //article is not expired
$query->where($db->quoteName('start') . ' != '. $db->quote(null)); //article is not null
$query->where($db->quoteName('start') . ' < '. $db->quote(date('Y-m-d') ."\n")); //article is started

//start query
$db->setQuery($query);
$results = $db->loadRowList(); // Row list, not objectlist.

$filename = 'user.csv';

header('Content-Type: text/csv; charset=utf-8');
header('Content-Disposition: attachment; filename=datax.csv');
$output = fopen("php://output", "w") or die;
$headers = array('id','message');//set headers
fputcsv($output, $headers) or die;  // input headers to output

foreach ($results as $row){
fputcsv($output, $row) or die;
}

fclose($output) or die;
jexit();
}

The function above will extract only two columns from the database called "__testdata", they are "id" and "message". If you need more columns to be exported, then adjust the script accordingly.

Good luck.

Rabu, 25 Juli 2012

Text Subxtractor


//5. get text and replaces them with shorter one in selected elements
text_substractor('div.article.xx', 'div.message',300);

function text_substractor(parent, children, limitText){
var myparent = document.id(document.body).getElements(parent);
myparent.each(function(element) {
var myChildren = element.getElement(children);
//get full text of div.message
var myText = myChildren.get('text');
var newText = myText.substr(1,limitText) + '...';
//destroy all elements inside myChildren.
myChildren.empty();
//set the new text on myChildren
myChildren.set('text', newText);
//add new element after text
var test = new Element('span', {class: 'test'});
test.inject(myChildren);
var mySpan = myChildren.getElement('span');
mySpan.setProperties({text:'readmore...',style:'background:yellow;'});
});
}
//5. end of text replacer

Element Width Adjuster

Html:
<div id="parent">
     <div id="child" class="columns-3">
     </div>

     <div id="child" class="columns-3 right">
     </div>
     <div id="child" class="columns-3 right">
     </div>
     <div id="child2" class="columns-2">
     </div>
     <div id="child2" class="columns-2 right">
     </div>
</div>

CSS:

#parent {width:900px; height:100px;float:left;}
#child {float:left;height:80px;background:#fdfdfd;}
#child2 {float:left;height:80px;background:#ffaaff;}

JavaScript

// Call the width setter function. commands: column_setter(name of element, name of element to have left margin , margin between element, and number of width set).
column_setter('.columns-3', 'right', 10, 3);
column_setter('.columns-2', 'right', 10, 2);

//6. function set elements width with element_name according to the parent's width;
function column_setter(myEls, myNextEls, marginBetweenElements, numberOfElements) {
var mycolumn = document.id(document.body).getElements(myEls);
var mydown2 = document.id(document.body).getElements(myEls +  myNextEls);
mydown2.setStyle('margin-left',marginBetweenElements);
mycolumn.each(function(element) {
//get Parent div
var myParent = element.getParent('div');
//measure Parent div's width
var parentsize = myParent.getSize();
var parentWidth = parentsize.x;
//measure Parent div's padding
paddingRight = myParent.getStyle('padding-right').toInt();
paddingLeft = myParent.getStyle('padding-left').toInt();
//measure Parent div's border
parentBorderLeft = myParent.getStyle('border-left').toInt();
parentBorderRight = myParent.getStyle('border-right').toInt();
// measure the margin. 3 columns has 2 margin. assume they are 5px each
var mycolumnwidth = (parentWidth - paddingRight - paddingLeft - parentBorderLeft - parentBorderRight - (marginBetweenElements*(numberOfElements-1)))/numberOfElements;
element.setStyle('width',mycolumnwidth);
});
}
//6. set elements width and height width