Magento type theme setup in Codeigniter - php

How can we setup multiple themes in codeigniter as in Magento?
I want to do this in HMVC CI.
I want to add theming feature with my development. I am using HMVC setup from Codeigniter HMVC
This is properly set and works fine.
This is a great development approach.
Here I am trying to add theme feature with this code, that could be controlled from admin panel.
/themes/themeName/templates/
/themes/themeName/modulesName/View
Approach is if view file not found in themes folder, it should come from
application/modules/moduleName.
What changes I have to do with this script ?
Can anyone suggest me what modification nee to do with this code?

Perhaps I misunderstood but why not extend CI's Loader class and add a theme function? I did this recently and it works great.
public function theme($view, $theme, $vars = array(), $return = FALSE) {
// Check if extension was specified. If not, add .php
$ext = pathinfo(APPPATH . $theme, PATHINFO_EXTENSION);
$view_file = ($ext == '') ? $view.'.php' : $view;
// Verify whether or not the requested theme file exists and set the template directory path prefix accordingly
if(file_exists(APPPATH . "views/store/theme/$theme/$view_file")) {
$this->_ci_view_paths = array(APPPATH . "views/store/theme/$theme/" => true);
}
else {
$this->_ci_view_paths = array(APPPATH . "views/store/theme/default/" => true);
}
return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
}

Related

Timber::render does not appear to work correctly on kinsta

I am migrating and troubleshooting a wordpress theme. I have a gutenberg block and an alert module set up to use the Timber composer package that allows the use of the twig templating engine.
I have it configured in a class
ProcessorTable.php
<?php
namespace CRG\Blocks;
class ProcessorTable
{
public function __construct()
{
$this->createProcessorTable();
}
public function createProcessorTable()
{
if (function_exists('acf_register_block')) {
// register a custom vue gravity forms block
acf_register_block(array(
'name' => 'processor-table-block',
'title' => __('Processor Table Block'),
'description' => __('A Block for displaying a contracted database processors table'),
'category' => 'crg-custom-blocks',
'icon' => 'welcome-write-blog',
'render_callback' => array($this, 'render_processor_table'),
'keywords' => array( 'table' ),
));
}
}
public function render_processor_table($block, $content = '', $is_preview = false)
{
$context = \Timber\Timber::context();
// Store block values.
$context['block'] = $block
// Store field values.
$context['fields'] = get_fields();
// Store $is_preview value.
$context['is_preview'] = $is_preview;
$twigPath = TEMPLATEPATH . "/src/views/blocks/block-processor-table.html.twig";
\Timber\Timber::render($twigPath, $context, 600);
}
}
AlertNotification.php
<?php
namespace CRG\Controllers\SiteWide;
class AlertNotification {
public function AlertModal(){
$context = \Timber\Timber::context();
$context['alert_header_text'] = get_field('alert_header_text', 'options');
$context['alert_text'] = get_field('alert_text', 'options');
$context['alert_icon'] = get_field('alert_icon', 'options');
$context['alert_color'] = get_field('alert_color', 'options');
$context['alert_toggle'] = get_field('alert_toggle', 'options');
\Timber\Timber::render( TEMPLATEPATH . "/src/views/sitewide/alert-modal.html.twig", $context );
}
}
this code worked on a cpanel server and on nexcess managed wordpress hosting, but when I migrated it to kinsta the code stopped rendering. It looks like the Timber::context() works, and the method can find the html.twig files, but it can't render the twig template, and produces no errors
I have tried troubleshooting this by checking the composer package versions, reinstalling the timber composer package, testing the code outside of the class directly into the functions.php file, and verifying the code can reach and output the file contents as a string. I checked the error log files and was unable to find a solution, or a cause of the error.
Hosting configuration:
Kinsta Caching: disabled
Wordpress debugging is enabled
Running on PHP 7.4
Using MySQL
I added this to my functions.php file
\Timber\Timber::$locations = TEMPLATEPATH . "/src/views";
so everything in the functions.php file for timber to work would look like this
require_once(__DIR__ . '/vendor/autoload.php');
$timber = new Timber\Timber();
\Timber\Timber::$locations = TEMPLATEPATH . "/src/views";
then in my ProcessorTable.php file I can call the Twig file path like this
$twigPath = "/blocks/block-processor-table.html.twig";
return \Timber\Timber::render( $twigPath, $context);
My guess about what went wrong is that the timber package was looking in the wrong director when rendering, based on incorrect locations information the Timber:locations method allows you to set up a custom location to store the templates: https://timber.github.io/docs/guides/template-locations/
Not sure why this would have worked on other systems, but not Kinsta. However, this appears to be a good practice going forward by explicitly setting the views.

English translation in overriding of template with module

I need to override a class and a template. To achieve this, I choose to create a new module in order to not be blocked when Prestashop will update. For overriding class, I don't have problem.
The worry is in overriding template, fields are in English whereas in the rest of my website, they are in French (when I uninstall the module, they come back in French).
In my module, I override the template with this way :
public function hookDisplayOverrideTemplate($params)
{
$controllerName = get_class($params['controller']);
$tpl = $this->local_path . 'override/tpl/' . $controllerName . '.tpl';
if (file_exists($tpl))
{
return $tpl;
}
return false;
}
In my .tpl file, the fields which are not translate are like this :
{l s='Your addresses'}
So, I tried to insert the fr.php file in /my_module/translations/fr.php, and I edited it :
<?php
global $_MODULE;
$_MODULE = array();
$_MODULE['<{customaddresses}prestashop>customaddresses_3908e1afa0ff22fbf112aff3c5ba55c1'] = 'Vos adresses';
Then, I modified the .tpl file :
{l s='Your addresses' mod='customaddresses'}
My fields are still in English.
Someone has a solution to suggest ?
After a great deal of research, I found my problem.
My solution is : $_MODULE['<{customaddresses}prestashop>address_0f68b904e33d9ac04605aecc958bcf52'] = 'Informations supplémentaires';
I replaced "customaddresses_" by "address_" (my overriding template).
I kept :
{l s='Your addresses' mod='customaddresses'}
And to be more proper, I changed a little bit my method hookDisplayOverrideTemplate :
public function hookDisplayOverrideTemplate($params)
{
$controllerName = get_class($params['controller']);
$tpl = $this->local_path . 'override/tpl/' . strtolower(str_replace("Controller", "", $controllerName)) . '.tpl';
if (file_exists($tpl))
{
return $tpl;
}
return false;
}

Is it possible to programmatically install plugins from wordpress theme

My dream is to include a php file in a theme which checks if a set of plugins are installed, and installs the ones which are not. Kind of like a set of dependencies for the theme, but also just a good way to package theme development to include a set of good plugins.
My questions...
Is there something like this in existence?
Is it possible to achieve from a single php file in a theme folder?
Are there any obvious pit-falls or problems with this approach?
How would I go about achieving this?
is it possible to enumerate installed plugins from within theme folder?
is it possible to download and place plugin files in the plugins folder?
is it possible to activate plugins from within theme directory?
07/06/2018 EDIT: If you are coming across this answer, the code highlighted below is extremely outdated and insecure and should not be used in any capacity outside of experimentation on a local server. If you are looking for a more modern solution for plugin management, consider installing Wordpress via Composer and Bedrock
I would advise NOT programatically checking for the existence of certain plugins, downloading, installing, and activating them from within any theme file. You have to consider that the check will be run every time the given page is loaded, and can result in a lot of superfluous code and unnecessary activity.
Instead, my advice would be to package any plugins on which your theme depends as a part of the theme itself, and NOT as a plugin. Plugins should be installed at the discretion of the user. If a theme depends on a plugin to function properly or efficiently, then it really should be packaged and downloaded with the theme itself.
But to answer your questions directly:
Probably. It is certainly possible to do.
Yes.
See the above. You potentially run into more issues by constantly checking for plugins and running a series of actions based on those conditions rather than just including everything needed.
Plenty of research
Probably
Yes
Yes
I cannot stress enough, however, that the purpose of a PLUGIN is to give the user the option to extend a given theme's capabilities. If your theme's capabilities DEPEND on existing plugins, then you really REALLY should include all the files when somebody downloads your theme.
Though if you feel that your approach benefits your theme in ways that I might be missing, feel free to write it however you like.
COMPLETE ANSWER: I decided to help create a proof of concept for you, because I got bored and curious. Much of this should be self explanatory. Add these functions:
function mm_get_plugins($plugins)
{
$args = array(
'path' => ABSPATH.'wp-content/plugins/',
'preserve_zip' => false
);
foreach($plugins as $plugin)
{
mm_plugin_download($plugin['path'], $args['path'].$plugin['name'].'.zip');
mm_plugin_unpack($args, $args['path'].$plugin['name'].'.zip');
mm_plugin_activate($plugin['install']);
}
}
function mm_plugin_download($url, $path)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$data = curl_exec($ch);
curl_close($ch);
if(file_put_contents($path, $data))
return true;
else
return false;
}
function mm_plugin_unpack($args, $target)
{
if($zip = zip_open($target))
{
while($entry = zip_read($zip))
{
$is_file = substr(zip_entry_name($entry), -1) == '/' ? false : true;
$file_path = $args['path'].zip_entry_name($entry);
if($is_file)
{
if(zip_entry_open($zip,$entry,"r"))
{
$fstream = zip_entry_read($entry, zip_entry_filesize($entry));
file_put_contents($file_path, $fstream );
chmod($file_path, 0777);
//echo "save: ".$file_path."<br />";
}
zip_entry_close($entry);
}
else
{
if(zip_entry_name($entry))
{
mkdir($file_path);
chmod($file_path, 0777);
//echo "create: ".$file_path."<br />";
}
}
}
zip_close($zip);
}
if($args['preserve_zip'] === false)
{
unlink($target);
}
}
function mm_plugin_activate($installer)
{
$current = get_option('active_plugins');
$plugin = plugin_basename(trim($installer));
if(!in_array($plugin, $current))
{
$current[] = $plugin;
sort($current);
do_action('activate_plugin', trim($plugin));
update_option('active_plugins', $current);
do_action('activate_'.trim($plugin));
do_action('activated_plugin', trim($plugin));
return true;
}
else
return false;
}
... and then execute like so:
$plugins = array(
array('name' => 'jetpack', 'path' => 'http://downloads.wordpress.org/plugin/jetpack.1.3.zip', 'install' => 'jetpack/jetpack.php'),
array('name' => 'buddypress', 'path' => 'http://downloads.wordpress.org/plugin/buddypress.1.5.5.zip', 'install' => 'buddypress/bp-loader.php'),
array('name' => 'tumblr-importer', 'path' => 'http://downloads.wordpress.org/plugin/tumblr-importer.0.5.zip', 'install' => 'tumblr-importer/tumblr-importer.php')
);
mm_get_plugins($plugins);
'name' can be anything, as it serves to be more of a temporary value. 'path' is exactly what it looks like, and is the direct URL to the zip file on the Wordpress server. The 'install' value is simply the path to the main PHP script that has all of the plugin information. You will have to know the layout of that particular plugin directory in order to fill out this information, as this is also required for the activation hack to work.
Activation function was found here (credit to sorich87): https://wordpress.stackexchange.com/questions/4041/how-to-activate-plugins-via-code
WARNING: This is by no means a very safe way to do things. I actually think that this can be abused quite easily, so our best bet is to use this as our baseline and try and improve from there.
If you should decide to use this approach, all I ask is that I'm credited with the initial overall script, along with sorich87 for his activation process may God have mercy on your soul.
07/06/2018 EDIT: Seriously, don't do this. By today's standards, this code is hot garbage. Plugin management should be done through Composer and Bedrock.
Inspired by the comment from Jamie Dixon I inspected how Wordpress works.
The process can be seen in /wp-admin/update.php from line 93. A short version could be made like this:
include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' ); //for plugins_api..
$plugin = 'plugin-name';
$api = plugins_api( 'plugin_information', array(
'slug' => $plugin,
'fields' => array(
'short_description' => false,
'sections' => false,
'requires' => false,
'rating' => false,
'ratings' => false,
'downloaded' => false,
'last_updated' => false,
'added' => false,
'tags' => false,
'compatibility' => false,
'homepage' => false,
'donate_link' => false,
),
));
//includes necessary for Plugin_Upgrader and Plugin_Installer_Skin
include_once( ABSPATH . 'wp-admin/includes/file.php' );
include_once( ABSPATH . 'wp-admin/includes/misc.php' );
include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );
$upgrader = new Plugin_Upgrader( new Plugin_Installer_Skin( compact('title', 'url', 'nonce', 'plugin', 'api') ) );
$upgrader->install($api->download_link);
If you don't want the feedback displayed you should create a custom Skin class. For example:
$upgrader = new \Plugin_Upgrader( new Quiet_Skin() );
class Quiet_Skin extends \WP_Upgrader_Skin {
public function feedback($string)
{
// just keep it quiet
}
}

How to combine / integrate CodeIgniter and Wordpress blogs functionality?

My website having feature requirement of blogging. I have to make blog which would look same like my website appearance.
How to combine CodeIgniter and Wordpress blogging(only) functionality such that it should look like within same website?
I have seen this question: Wordpress template with codeigniter. But didn't got much clue.
Seems like a bit of overkill.
Why not use a Restful service like json_api to retrieve your posts, then copy over the css file(parts)?
You do this you will need to create 2 files and modify 2 existing functions. One function is in CodeIgniter and the other is in Wordpress.
Here are the steps.
1.) Open your configs/hooks.php file and create a pre_controller hook as follows:
$hook['pre_controller'] = array(
'class' => '',
'function' => 'wp_init',
'filename' => 'wordpress_helper.php',
'filepath' => 'helpers'
);
2.) Create a new file in your helpers directory called 'wordpress_helper.php', and add the following code to it:
/**
*
*/
function wp_init(){
$CI =& get_instance();
$do_blog = TRUE; // this can be a function call to determine whether to load CI or WP
/* here we check whether to do the blog and also we make sure this is a
front-end index call so it does not interfere with other CI modules.
*/
if($do_blog
&& ($CI->router->class == "index" && $CI->router->method == "index")
)
{
// these Wordpress variables need to be globalized because this is a function here eh!
global $post, $q_config, $wp;
global $wp_rewrite, $wp_query, $wp_the_query;
global $allowedentitynames;
global $qs_openssl_functions_used; // this one is needed for qtranslate
// this can be used to help run CI code within Wordpress.
define("CIWORDPRESSED", TRUE);
require_once './wp-load.php';
define('WP_USE_THEMES', true);
// Loads the WordPress Environment and Template
require('./wp-blog-header.php');
// were done. No need to load any more CI stuff.
die();
}
}
3.) Open wp-includes/link-template.php and made the following edit:
if ( ! function_exists('site_url'))
{
function site_url( $path = '', $scheme = null ) {
return get_site_url( null, $path, $scheme );
}
}
4.) Copy url_helper.php from the CodeIgniter helper folder to your APPPATH helper folder
and make the following edit:
if ( ! function_exists('site_url'))
{
function site_url($uri = '', $scheme = null)
{
// if we are in wordpress mode, do the wordpress thingy
if(defined('CIWORDPRESSED') && CIWORDPRESSED){
return get_site_url( null, $path, $scheme );
}else{
$CI =& get_instance();
return $CI->config->site_url($uri);
}
}
}
The steps above will allow you to dynamically load either your CI app or your WP site based on some simple filtering. It also gives you access to all CI functionality within WP of that is something you can use.

how to auto load mobile templates by agent in codeigniter?

dir:
application
-controllers
-models
-views
-mobile_views
How do I auto load templates at mobile_views when I use $this->load->view and view by iphone or other mobile phone?
Check this
You can do it in two way.
Way 1: Its very simple. In the above answer (the link I have given) add following line in the end of MyController function
$this->load->_ci_view_path . = $this->view_type .'/';
You are done. You can simply load view like normal view load.
Way 2:
To autoload a view based on user agent, I think you can implement it using hooks. To implement this hooks you need to follow the following steps
Autoload user agent library in autoload.php
$autoload['libraries'] = array('user_agent');
Enable hooks in config.php
$config['enable_hooks'] = TRUE;
Not implement hooks on post_controller_constructor. Add following codes to hooks.php
$hook['post_controller_constructor'][] = array('class' => 'Loadview',
'function' => 'load',
'filename' => 'loadview.php',
'filepath' => 'hooks'
);
Now create a page named loadview.php under hooks directory having following code
class Loadview
{
public static $MOBILE_PLATFORM = 'mobile';
public static $DEFAULT_PLATFORM = 'default';
public function load(){
$this->CI =& get_instance();
$view_type = $this->CI->agent->is_mobile() ? self::$MOBILE_PLATFORM : self::$DEFAULT_PLATFORM;
$this->CI->load->_ci_view_path = $this->CI->load->_ci_view_path . $view_type .'/';
}
}
You are done now. You can simply load view like normal view load.
to load views from another dir aside from "views", i found this forum topic to be helpful
http://codeigniter.com/forums/viewthread/132960/
function external_view($path, $view, $vars = array(), $return = FALSE)
{
$full_path = $path.$view.'.php';
if (file_exists($full_path))
{
return $this->_ci_load(array('_ci_path' => $full_path, '_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
}
else
{
show_error('Unable to load the requested module template file: '.$view);
}
}
and you can work the rest from the controller.
I do this in my controller:
public function index()
{
if($this->agent->is_mobile())
{
$this->load_mobile();
}
else
{
$this->load_web();
}
}
public function load_mobile()
{
$this->load->view('mobile/home');
}
public function load_web()
{
$this->load->view('web/home');
}
In this way I can add different data to mobile and to web pages.
I also extend the default controller and add some useful extra features:
Enables the usage of master page/templates.
Can add css and javascript files.
Uses the _output method for controlling the controllers output.
Can load relative content with in the form of modules (views)
So I can manage better the different pages.
Bye!!

Categories