Jump to content

[SOLVED] function install()


nsuriac
 Share

Recommended Posts

Hello! I'm new in Prestashop development and I'm following a book called Prestashop Module development, from Fabien Serny.

 

It's very interesting and helpful. However, there is something that I can't understand, and I thought that maybe someone here can help me.

 

The problem is located in the "public function install()" where I call the "parent::install()". Lets see:

 

The code above works on the code attached in the book, but not if i copy it on my code. 

public function install()
	{
		// Call install parent method
		if (!parent::install())
			return false;

		// Execute module install SQL statements
		$sql_file = dirname(__FILE__).'/install/install.sql';
		if (!$this->loadSQLFile($sql_file))
			return false;

		// Register hooks
		if (!$this->registerHook('displayProductTabContent') ||
			!$this->registerHook('displayBackOfficeHeader'))
			return false;

		// Preset configuration values
		Configuration::updateValue('MYMOD_GRADES', '1');
		Configuration::updateValue('MYMOD_COMMENTS', '1');

		// All went well!
		return true;
	}

How can the first if statement ever return true if it's never called before? And the same for loadSQLFile and registerHook. 

 

I tried to do it in the way I think is more logical, and it works: 

public function install()
	{
	
	    parent::install();

		$sql_file = dirname(__FILE__).'/install/install.sql';
	    $this->loadSQLFile($sql_file);
		

	
		$this->registerHook('displayProductTabContent');
        $this->registerHook('displayBackOfficeHeader');


		Configuration::updateValue('MYMOD_GRADES', '1');
		Configuration::updateValue('MYMOD_COMMENTS', '1');
        return true;
	}

So my questions are: 

 

1. how can the firts code I posted work if the methods that apear inside the if statments arn't ever called?

 

2. why if I copy the code it dosn't work in my module if it does on the code from the book?

 

There you go both full codes:

<?php

class MyModComments extends Module
{
	public function __construct()
	{
		$this->name = 'mymodcomments';
		$this->tab = 'front_office_features';
		$this->version = '0.2';
		$this->author = 'Fabien Serny';
		$this->bootstrap = true;
		parent::__construct();
		$this->displayName = $this->l('My Module of product comments');
		$this->description = $this->l('With this module, your customers will be able to grade and comments your products.');
	}

	public function install()
	{
		// Call install parent method
		if (!parent::install())
			return false;

		// Execute module install SQL statements
		$sql_file = dirname(__FILE__).'/install/install.sql';
		if (!$this->loadSQLFile($sql_file))
			return false;

		// Register hooks
		if (!$this->registerHook('displayProductTabContent') ||
			!$this->registerHook('displayBackOfficeHeader'))
			return false;

		// Preset configuration values
		Configuration::updateValue('MYMOD_GRADES', '1');
		Configuration::updateValue('MYMOD_COMMENTS', '1');

		// All went well!
		return true;
	}

	public function uninstall()
	{
		// Call uninstall parent method
		if (!parent::uninstall())
			return false;

		// Execute module install SQL statements
		$sql_file = dirname(__FILE__).'/install/uninstall.sql';
		if (!$this->loadSQLFile($sql_file))
			return false;

		// Delete configuration values
		Configuration::deleteByName('MYMOD_GRADES');
		Configuration::deleteByName('MYMOD_COMMENTS');

		// All went well!
		return true;
	}

	public function loadSQLFile($sql_file)
	{
		// Get install SQL file content
		$sql_content = file_get_contents($sql_file);

		// Replace prefix and store SQL command in array
		$sql_content = str_replace('PREFIX_', _DB_PREFIX_, $sql_content);
		$sql_requests = preg_split("/;\s*[\r\n]+/", $sql_content);

		// Execute each SQL statement
		$result = true;
		foreach($sql_requests as $request)
			if (!empty($request))
				$result &= Db::getInstance()->execute(trim($request));

		// Return result
		return $result;
	}


	public function onClickOption($type, $href = false)
	{
		$confirm_reset = $this->l('Reseting this module will delete all comments from your database, are you sure you want to reset it ?');
		$reset_callback = "return mymodcomments_reset('".addslashes($confirm_reset)."');";

		$matchType = array(
			'reset' => $reset_callback,
			'delete' => "return confirm('Confirm delete?')",
		);

		if (isset($matchType[$type]))
			return $matchType[$type];

		return '';
	}

	public function hookDisplayBackOfficeHeader($params)
	{
		// If we are not on section modules, we do not add JS file
		if (Tools::getValue('controller') != 'AdminModules')
			return '';

		// Assign module mymodcomments base dir
		$this->context->smarty->assign('pc_base_dir', __PS_BASE_URI__.'modules/'.$this->name.'/');

		// Display template
		return $this->display(__FILE__, 'displayBackOfficeHeader.tpl');
	}

	public function processProductTabContent()
	{
		if (Tools::isSubmit('mymod_pc_submit_comment'))
		{
			$id_product = Tools::getValue('id_product');
			$firstname = Tools::getValue('firstname');
			$lastname = Tools::getValue('lastname');
			$email = Tools::getValue('email');
			$grade = Tools::getValue('grade');
			$comment = Tools::getValue('comment');
			$insert = array(
				'id_product' => (int)$id_product,
				'firstname' => pSQL($firstname),
				'lastname' => pSQL($lastname),
				'email' => pSQL($email),
				'grade' => (int)$grade,
				'comment' => pSQL($comment), 'date_add' => date('Y-m-d H:i:s'),
			);
			Db::getInstance()->insert('mymod_comment', $insert);
			$this->context->smarty->assign('new_comment_posted', 'true');
		}
	}

	public function assignProductTabContent()
	{
		$enable_grades = Configuration::get('MYMOD_GRADES');
		$enable_comments = Configuration::get('MYMOD_COMMENTS');

		$id_product = Tools::getValue('id_product');
		$comments = Db::getInstance()->executeS('
		SELECT * FROM `'._DB_PREFIX_.'mymod_comment`
		WHERE `id_product` = '.(int)$id_product);

		$this->context->controller->addCSS($this->_path.'views/css/star-rating.css', 'all');
		$this->context->controller->addJS($this->_path.'views/js/star-rating.js');

		$this->context->controller->addCSS($this->_path.'views/css/mymodcomments.css', 'all');
		$this->context->controller->addJS($this->_path.'views/js/mymodcomments.js');

		$this->context->smarty->assign('enable_grades', $enable_grades);
		$this->context->smarty->assign('enable_comments', $enable_comments);
		$this->context->smarty->assign('comments', $comments);
	}

	public function hookDisplayProductTabContent($params)
	{
		$this->processProductTabContent();
		$this->assignProductTabContent();
		return $this->display(__FILE__, 'displayProductTabContent.tpl');
	}

	public function processConfiguration()
	{
		if (Tools::isSubmit('mymod_pc_form'))
		{
			$enable_grades = Tools::getValue('enable_grades');
			$enable_comments = Tools::getValue('enable_comments');
			Configuration::updateValue('MYMOD_GRADES', $enable_grades);
			Configuration::updateValue('MYMOD_COMMENTS', $enable_comments);
			$this->context->smarty->assign('confirmation', 'ok');
		}
	}

	public function assignConfiguration()
	{
		$enable_grades = Configuration::get('MYMOD_GRADES');
		$enable_comments = Configuration::get('MYMOD_COMMENTS');
		$this->context->smarty->assign('enable_grades', $enable_grades);
		$this->context->smarty->assign('enable_comments', $enable_comments);
	}

	public function getContent()
	{
		$this->processConfiguration();
		$this->assignConfiguration();
		return $this->display(__FILE__, 'getContent.tpl');
	}
}

<?php

class MyModComments extends Module
{
	public function __construct()
	{
		$this->name = 'mymodcomments';
		$this->tab = 'front_office_features';
		$this->version = '0.1';
		$this->author = 'Nil Surià';
		$this->bootstrap = true;
		parent::__construct();
		$this->displayName = $this->l('My Module of product comments');
		$this->description = $this->l('With this module, your customers will be able to grade and comments your products.');
	}

	public function install()
	{
		
		if (!parent::install())
			return false;


		$sql_file = dirname(__FILE__).'/install/install.sql';
		if (!$this->loadSQLFile($sql_file))
			return false;

	
		if (!$this->registerHook('displayProductTabContent') ||
			!$this->registerHook('displayBackOfficeHeader'))
			return false;


		Configuration::updateValue('MYMOD_GRADES', '1');
		Configuration::updateValue('MYMOD_COMMENTS', '1');

	
		return true;
	}
    
     public function loadSQLFile($sql_file)
	{
		$sql_content = file_get_contents($sql_file);
		$sql_content = str_replace('PREFIX_', _DB_PREFIX_, $sql_content);
		$sql_requests = preg_split("/;\s*[\r\n]+/", $sql_content);

		$result = true;
		foreach($sql_requests as $request)
			if (!empty($request))
				$result &= Db::getInstance()->execute(trim($request));

	}
    
  	public function processProductTabContent()
	{
		if (Tools::isSubmit('mymod_pc_submit_comment'))
		{
			$id_product = Tools::getValue('id_product');
			$grade = Tools::getValue('grade');
			$comment = Tools::getValue('comment');
			$insert = array(
				'id_product' => (int)$id_product,
				'grade' => (int)$grade,
				'comment' => pSQL($comment),
				'date_add' => date('Y-m-d H:i:s'),
			);
			Db::getInstance()->insert('mymod_comment', $insert);
			$this->context->smarty->assign('new_comment_posted', 'true');
		}
	}

	public function assignProductTabContent()
	{
		$enable_grades = Configuration::get('MYMOD_GRADES');
		$enable_comments = Configuration::get('MYMOD_COMMENTS');

		$id_product = Tools::getValue('id_product');
		$comments = Db::getInstance()->executeS('
		SELECT * FROM `'._DB_PREFIX_.'mymod_comment`
		WHERE `id_product` = '.(int)$id_product);

		$this->context->controller->addCSS($this->_path.'views/css/star-rating.css', 'all');
		$this->context->controller->addJS($this->_path.'views/js/star-rating.js');

		$this->context->controller->addCSS($this->_path.'views/css/mymodcomments.css', 'all');
		$this->context->controller->addJS($this->_path.'views/js/mymodcomments.js');

		$this->context->smarty->assign('enable_grades', $enable_grades);
		$this->context->smarty->assign('enable_comments', $enable_comments);
		$this->context->smarty->assign('comments', $comments);
	}

	public function hookDisplayProductTabContent($params)
	{
		$this->processProductTabContent();
		$this->assignProductTabContent();
		return $this->display(__FILE__, 'displayProductTabContent.tpl');
	}

	public function processConfiguration()
	{
		if (Tools::isSubmit('mymod_pc_form'))
		{
			$enable_grades = Tools::getValue('enable_grades');
			$enable_comments = Tools::getValue('enable_comments');
			Configuration::updateValue('MYMOD_GRADES', $enable_grades);
			Configuration::updateValue('MYMOD_COMMENTS', $enable_comments);
			$this->context->smarty->assign('confirmation', 'ok');
		}
	}

	public function assignConfiguration()
	{
		$enable_grades = Configuration::get('MYMOD_GRADES');
		$enable_comments = Configuration::get('MYMOD_COMMENTS');
		$this->context->smarty->assign('enable_grades', $enable_grades);
		$this->context->smarty->assign('enable_comments', $enable_comments);
	}

	public function getContent()
	{
		$this->processConfiguration();
		$this->assignConfiguration();
		return $this->display(__FILE__, 'getContent.tpl');
	}
    
}

If anyone had read up here it deserves a big applause. Thank you! 

Share this post


Link to post
Share on other sites

The line:

 

        if (!parent::install())

 
 
What it does:
- it first calls the function parent::install() the function gives some return value (normally true or false
- it inverses the answer using the '!'    (like    !(true)    becomes    false  )
- it checks the value (using the if statement) and takes action if the comparison answers as true
 
 
So in our case:
if the function parent::install() returns FALSE (i.e. something went wrong), it inverses the answer (NOT false => true), it compares and if true, it returns false (i.e. abort our own install function)
 
If the parent::install all went OK, it returned TRUE, so after inversion NOT true -> false , then compare if( false)     (which is not correct ( not 'true') so it will NOT executes the command return false and just continues with the next command.
 
 
 
You could rewrite it as follows to make it more clear:
 
  $resultCorrect = parent::install();
  if (!$resultCorrect)    // i.e. if NOT correct result
     return false;
 
But the original statement does the same (and doesn't have to store the parent::install() result, which saves time and a tiny bit of memory.
 
 
Why the install function doesn't work:
I expect that in your own module, you don't have any database changes, and thus don't have the file :
modules/yourmodule/install/install.sql
If indees this file isn't there, the following code will fail:
 
        $sql_file = dirname(__FILE__).'/install/install.sql';
        if (!$this->loadSQLFile($sql_file))
            return false;

 

 

Let's break it up in some parts:

        $sql_file = dirname(__FILE__).'/install/install.sql';

 

Here the variable $sql_file get's the path and file name, as indicated above.

 

        if (!$this->loadSQLFile($sql_file))

 

The $this->loadSQLFile($sql_file) calls the function loadSQLFile()   (defined in this module class)

This function will be aborted when any error occurs, like loading the file etc. with return value false

So if you compare again the inverse value (NOT (anythingWentWrong?)

 then it will execute the command:

            return false;

Which will abort the install() function, and in turn will abort the full module installation.
 
Hope this is what you were looking for. If not, please elaborate a little more.
pascal
  • Like 1

Share this post


Link to post
Share on other sites

Hi Pascal! thank you a lot for your time and your fast answer. 

 

I understand how "!" (NOT) operator works. What I didn't know is that when you execute an "if" statement, it execute the condition and don't just compare if that condition is true or false. Then, I could not understand how was it possible that the "parent::install()" was executed if it was not ever called.

 

Since I have a very bad English, I will try to explain it with an example:

 

In the code above, the if statement condition "test()" will be converted to "true" Boolean since it's an string. Then the "!" (NOT) operator will convert that to "false" and the "echo "$nworking" will be ignored. If I execute the script nothing appear in the screen. I find it logical because I didn't executed the "test()"  function. The if statement just check (compare) if it's true or false.  

 

Then, if "test()" is not executed, I can't understand how is it possible that "parent::install()" is executed and produce the installation if that function is never called!

<?php

$working = "it's working";
$nworking = "is not working";

function test() {
echo "$working";
}
if(!test()) {echo "$nworking";}

?> 

 I really appreciate your answers and sorry if it's a stupid question. 

 

Thank you very much!

Edited by nsuriac (see edit history)

Share this post


Link to post
Share on other sites

First of all, In php the scope of variables are a little different than for example c/c++. So it doesn't know $working inside the function test()

Also, the echo should not have the double quotes around them, as otherwise it regards the $working as literal text '$working'

Finally, the function just echo's the text, but does not return it. When there's no explicit return value returned, it assumes false.

 

 

Let's make some simple test:

 

<?php
 
  function test() {
    echo "inside the test function</br>";
    return true;     // toggle between true and false to see result.
                     // if you take the whole return line out, it will return false
  }
 
  if(!test())
    echo "test didn't return true";
  else
    echo "test returned true";
 
?>
 

Running this will show the lines:

 

inside the test function
test returned true

 

When changing the return value true to false inside the test function will give this:

inside the test function
test didn't return true

 

N.B.

When you leave the return command out, it will return an implicit false.

Also if you return the value 0, it will be regarded as a false.

 

If you return -1, or 5, or 'hi' etc, it's all regarded as a true.

 

Hope this helps,

pascal

  • Like 1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

Cookies ensure the smooth running of our services. Using these, you accept the use of cookies. Learn More