Jump to content
Latest News: (loading..)
frankl

How to make a 2.4 App

Recommended Posts

Did you say you want a hook for that?

 

post-3583-0-06393200-1490321416_thumb.gif

We can do that, but first we need to make a couple of minor changes to the categories.php page because it's not properly set up to take new page tabs.

in catalog/admin/categories.php change this
 

<div class="row">
  <div id="productLanguageTabs">
    <ul class="nav nav-tabs">

                
to this
 

<div class="row">
  <div id="productLanguageTabs">
    <ul class="nav nav-tabs2">

and this
 

<?php
      for ($i=0, $n=sizeof($languages); $i<$n; $i++) {
        echo '<li ' . ($i === 0 ? 'class="active"' : '') . '><a data-target="#section_general_content_' . $languages[$i]['directory'] . '" data-toggle="tab">' . $OSCOM_Language->getImage($languages[$i]['code']) . ' ' . $languages[$i]['name'] . '</a></li>';
      }
?>

                </ul>

                <div class="tab-content">

                
to this
 

<?php
      for ($i=0, $n=sizeof($languages); $i<$n; $i++) {
        echo '<li ' . ($i === 0 ? 'class="active"' : '') . '><a data-target="#section_general_content_' . $languages[$i]['directory'] . '" data-toggle="tab">' . $OSCOM_Language->getImage($languages[$i]['code']) . ' ' . $languages[$i]['name'] . '</a></li>';
      }
?>

                </ul>

                <div class="tab-content2">

All we've done is add the number 2 next to nav-tabs and tab-content.
               
We need to do that otherwise the extra tab that gets added in gets added in twice and screws up the display.

Perhaps @@Harald Ponce de Leon will change this in the future to allow admin/products tab hooks. Or maybe I've done it the wrong way?

We need to tell osCommerce that we are introducing hooks into the categories page, so go back to the trusty oscommerce.json file and put in the required information.

Change this
 

    "modules": {
        "AdminMenu": {
            "Test":    "Module\\Admin\\Menu\\Test"
        },
        "Content": {
            "product_info": {
                "PIRELATED":    "Module\\Content\\PIRELATED"
            }

        }
    },

to this        
 

    "modules": {
        "AdminMenu": {
            "Related":    "Module\\Admin\\Menu\\Related"
        },
        "Content": {
            "product_info": {
                "PIRELATED":    "Module\\Content\\PIRELATED"
            }
        },
        "Hooks": {
            "Admin/Products": {
                "Action":    "Module\\Hooks\\Admin\\Products\\Action",
                "Page":        "Module\\Hooks\\Admin\\Products\\PageTab"
            }
        }

    },

    
Note: I'm now altering the files from the Github repository, so the Vendor, App, and Module names have changed from the posts above.

Now to create the actual hook, make a new folder OSC/Apps/FrankL/Related/Module/Hooks/Admin/Products

In that folder, create the Action file, Action.php
 

<?php
/**
  * Related Products App for osCommerce Online Merchant
  *
  * @[member='copyright'] (c) 2016 Frank Ludriks; https://www.ink-cartridge.com.au
  * @[member='licensed2kill'] MIT; https://www.oscommerce.com/license/mit.txt
  */

namespace OSC\Apps\FrankL\Related\Module\Hooks\Admin\Products;

use OSC\OM\HTML;
use OSC\OM\OSCOM;
use OSC\OM\Registry;

use OSC\Apps\FrankL\Related\Related as RelatedApp;

class Action implements \OSC\OM\Modules\HooksInterface
{
    protected $app;
    protected $ms;

    public function __construct()
    {
        if (!Registry::exists('Related')) {
            Registry::set('Related', new RelatedApp());
        }

        $this->app = Registry::get('Related');

        $this->ms = Registry::get('MessageStack');

        $this->app->loadDefinitions('hooks/admin/products/action');
    }

    public function execute()
    {

    
    }


}


and also a file PageTab.php
 

<?php
/**
  * Related Products App for osCommerce Online Merchant
  *
  * @[member='copyright'] (c) 2016 Frank Ludriks; https://www.ink-cartridge.com.au
  * @[member='licensed2kill'] MIT; https://www.oscommerce.com/license/mit.txt
  */

namespace OSC\Apps\FrankL\Related\Module\Hooks\Admin\Products;

use OSC\OM\HTML;
use OSC\OM\OSCOM;
use OSC\OM\Registry;

use OSC\Apps\FrankL\Related\Related as RelatedApp;

class PageTab implements \OSC\OM\Modules\HooksInterface
{
    protected $app;

    public function __construct()
    {
        if (!Registry::exists('Related')) {
            Registry::set('Related', new RelatedApp());
        }

        $this->app = Registry::get('Related');
    }

    public function display()
    {

        if (!defined('OSCOM_APP_FRANKL_RELATED_STATUS')) {
            return false;
        }

        $this->app->loadDefinitions('hooks/admin/products/tab');

        $output = '';

        $status = [];
        
        $info = '';
        
        $data = '';

        
        //check for masters
            $Qcheck = $this->app->db->prepare('select * from :table_products_related_products where pop_products_id_master = :products_id and pop_products_id_slave != :products_id');
            $Qcheck->bindInt(':products_id', $_GET['pID']);
            $Qcheck->execute();
            if ($Qcheck->fetch() !== false) {
                $master_query = 'select pop_products_id_slave
                                  from :table_products_related_products
                                  where pop_products_id_master = :products_id';
                $Qmaster = $this->app->db->prepare($master_query);
                $Qmaster->bindInt(':products_id', $_GET['pID']);
                $Qmaster->execute();
                
                $info .=  '<div class="col-sm-5"><table class="table table-hover">' .
                            ' <thead>' .
                            '    <tr class="info">' .
                            '      <th>' . $this->app->getDef('heading_master') . '</th>' .
                            '    </tr>' .
                            '  </thead>';
                
                  while ($Qmaster->fetch()) {
                
                    $related_query = 'select pa.*, pd.products_id, pd.products_name
                                      from :table_products_related_products pa
                                      left join :table_products_description pd
                                      on pa.pop_products_id_slave = pd.products_id
                                      and pd.language_id = :languages_id
                                      left join :table_products p
                                      on p.products_id = pd.products_id
                                      where pd.products_id = :products_id';
                    $Qrelated = $this->app->db->prepare($related_query);
                    $Qrelated->bindInt(':products_id', $Qmaster->value('pop_products_id_slave'));
                    $Qrelated->bindInt(':languages_id', $this->app->lang->getId());
                    $Qrelated->execute();
                  
                     while ($Qrelated->fetch()) {
                        $info .= '  <tr>' .
                            '    <td>' .
                            '      ' . $Qrelated->value('products_name') .
                            '   </td>' .
                            '  </tr>';
                    }
                   
                  }
                
                $info .=  '</table></div>';
                
            } else {
                
                $info .=    '<div class="col-sm-5"><table class="table table-hover">' .
                            ' <thead>' .
                            '    <tr class="info">' .
                            '      <th>' . $this->app->getDef('heading_master') . '</th>' .
                            '    </tr>' .
                            '  </thead>' .
                            '   <tr>' .
                            '      <td>' .
                            '        <div class="alert alert-warning col-sm-5" role="alert">' . $this->app->getDef('no_products') . '</div>' .
                            '      </td>' .
                            '    </tr>' .
                            '</table></div>';
                    
            }
                
        //check for slaves
                
            $Qcheck = $this->app->db->prepare('select * from :table_products_related_products where pop_products_id_slave = :products_id');
            $Qcheck->bindInt(':products_id', $_GET['pID']);
            $Qcheck->execute();
              if ($Qcheck->fetch() !== false) {
                $slave_query = 'select pop_products_id_master
                                from :table_products_related_products
                                where pop_products_id_slave = :products_id';
                $Qslave = $this->app->db->prepare($slave_query);
                $Qslave->bindInt(':products_id', $_GET['pID']);
                $Qslave->execute();
                
                
                $info .=  '<div class="col-sm-5"><table class="table table-hover">' .
                            ' <thead>' .
                            '    <tr class="info">' .
                            '      <th>' . $this->app->getDef('heading_slave') . '</th>' .
                            '    </tr>' .
                            '  </thead>';
                
                
                  while ($Qslave->fetch()) {
                
                    $related_query = 'select pa.*, pd.products_id, pd.products_name
                                      from :table_products_related_products pa
                                      left join :table_products_description pd
                                      on pa.pop_products_id_master = pd.products_id
                                      and pd.language_id = :languages_id
                                      left join :table_products p
                                      on p.products_id = pd.products_id
                                      where pd.products_id = :products_id and pa.pop_products_id_slave = :pop_products_id_slave';
                    $Qrelated = $this->app->db->prepare($related_query);
                    $Qrelated->bindInt(':products_id', $Qslave->value('pop_products_id_master'));
                    $Qrelated->bindInt(':pop_products_id_slave', $_GET['pID']);
                    $Qrelated->bindInt(':languages_id', $this->app->lang->getId());
                    $Qrelated->execute();

                     while ($Qrelated->fetch()) {
                        $info .= '  <tr>' .
                                 '    <td>' .
                                 '      ' . $Qrelated->value('products_name') .
                                 '   </td>' .
                                 '  </tr>';
                     
                     }
                  
                  }
                    
                    $info .=  '</table></div>';
                   
                   } else {
                $info .=    '<div class="col-sm-5"><table class="table table-hover">' .
                            ' <thead>' .
                            '    <tr class="info">' .
                            '      <th>' . $this->app->getDef('heading_slave') . '</th>' .
                            '    </tr>' .
                            '  </thead>' .
                            '   <tr>' .
                            '      <td>' .
                            '        <div class="alert alert-warning col-sm-5" role="alert">' . $this->app->getDef('no_products') . '</div>' .
                            '      </td>' .
                            '    </tr>' .
                            '</table></div>';
                    
              }
                
                

                $related_button = HTML::button($this->app->getDef('button_manage'), 'fa fa-arrows-h', $this->app->link('Admin&products_id_view=' . $_GET['pID']), null, 'btn-info');
                
                $data .= '<div class="panel panel-info oscom-panel">' .
                        '  <div class="panel-body">' .
                        '    <div class="container-fluid">' .
                        '      <div class="row">' .
                        '        ' . $info .
                        '      </div>' .
                        '      <div class="text-center">' .
                        '        ' . $related_button .
                        '      </div>' .
                        '    </div>' .
                        '  </div>' .
                        '</div>';
                
                $tab_title = addslashes($this->app->getDef('tab_title'));

                $output = <<<EOD
<div id="section_relatedAppRelated_content" class="tab-pane oscom-m-top-15">
  {$data}
</div>

<script>
$('#section_relatedAppRelated_content').appendTo('#productTabs .tab-content');
$('#productTabs .nav-tabs').append('<li><a data-target="#section_relatedAppRelated_content" data-toggle="tab">{$tab_title}</a></li>');
</script>
EOD;

        return $output;
    }


}


As usual, we need to create language definition files, so you need to create a new folder OSC/Apps/FrankL/Related/languages/english/hooks/admin/products
                                                    
and in that folder create a file tab.txt with the following contents
 

button_manage = Manage Related Products
tab_title = Related Products
no_products = None
heading_master = Master of...
heading_slave = Slave of...

That's it. Now go to a product edit page and you'll have a new tab called Related Products.

You can also check to see which hooks are installed by selecting Legacy -> Modules -> Hooks

Edited by frankl

Let's make things easier for new osCommerce users http://forums.oscommerce.com/topic/402638-discussion-about-hard-coded-database-tables/?p=1718900  Getting there with osCommerce 2.4! :thumbsup:

Share this post


Link to post
Share on other sites

@@frankl

		$data = '<div id="section_relatedAppRelated_content" class="tab-pane oscom-m-top-15">' . $data . '</div>';

                $tab_title = addslashes($this->app->getDef('tab_title'));

                $output = <<<EOD
<script>
$('{$data}').insertAfter('div#section_images_content');

$('#productTabs ul:first').append('<li><a data-target="#section_relatedAppRelated_content" data-toggle="tab">{$tab_title}</a></li>');
</script>
EOD;

:thumbsup:


:blink:
osCommerce based shop owner with minimal design and focused on background works. When the less is more.
Email managment with tracking pixel, package managment for shipping, stock management, warehouse managment with bar code reader, parcel shops management on 3000 pickup points without local store.

Share this post


Link to post
Share on other sites

@@frankl, all is working, easy peasy, I need to buy u a beer! Thx!

 

Can't wait to see the full app market place roll out. It's gonna be good! And this doesn't have the resource hog issues like other carts that I dislike.

Share this post


Link to post
Share on other sites

@@Gergely

@@wHiTeHaT

 

Thanks for that. Github updated with Gergely and Henry's changes.

 

@@clustersolutions

 

Thanks for testing. Beer welcome if we ever meet ;)


Let's make things easier for new osCommerce users http://forums.oscommerce.com/topic/402638-discussion-about-hard-coded-database-tables/?p=1718900  Getting there with osCommerce 2.4! :thumbsup:

Share this post


Link to post
Share on other sites

@@frankl you should actually use a real Vendor and App name for your example instead of Test Test, and make a note that developers must use their own Vendor and App code names (registrations will open for this when the Apps Marketplace goes live).

 

There is also a Content Module hook you can define in your json metadata file. This should automatically load your module - you just need to take care of an administration page if parameters are to be set.

 

In case anyone has missed it, some documentation is up at:

 

https://library.oscommerce.com/Online&en&oscom_2_4&developers&apps

 

 

I'm curious on how this will work. Will still be allowed to just upload an app via ftp or will be mandatory to download and install them via the marketplace?

Share this post


Link to post
Share on other sites

I am saying the bootstrap version dont have OSC folder; will it have one in future? For example the RMA syystem u made is an app for bootstrap correct? So what procedure is different when doing an app for bootstrap?

Share this post


Link to post
Share on other sites

The 2.3 series won't ever have an OSC folder. The OSC folder is unique to 2.4, it is used for site template and app purposes.

Creating an app for osC 2.3.4BS is completely different from creating an app for osC 2.4 for this reason.

To install an app for osC 2.3 series you just create the files you need and upload them, whereas apps for 2.4 will need a strict hierarchical structure and defined configuration files which tell osCommerce where required files are stored.


Let's make things easier for new osCommerce users http://forums.oscommerce.com/topic/402638-discussion-about-hard-coded-database-tables/?p=1718900  Getting there with osCommerce 2.4! :thumbsup:

Share this post


Link to post
Share on other sites

@frankl

Thank you for this post.

In 2009 my first learn about osC, with a little bit c++ program knowledge learn long time ago at school, it took me 6 months to read all the posts, practices to install addons, and finally start a osC shopping cart system. Others suggested me to go wordpress as better and easier to design a beautiful website... I stay with osC as I love the community supports and real free open source concepts!

And this post, good title, and explain, steps by steps guides, less then 6 minutes to follow through.....love it and thank you!!!

Lyn

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

×