Creating Module for Admin and Clients with Perfex CRM - Assistance Required - php

I am working on creating a module for prefex CRM. What this module will be doing is pretty simple, but is quickly turning into more than I anticipated. Allow me to explain what I'm doing and where I'm stuck. I am hoping someone can offer some advice.
Admin View
Admin Module that adds menu item 'Mail' to the side nav bar
When clicking this menu item, a page loads that uses the already uses the drag & drop file upload feature prefex CRM has built in.
When a staff member uploads a file, a modal launches with a form that asks users who the upload should be assigned to. It should use autocomplete to select the customer to attach the file to.
The upload date/time is recorded in database and the record entry in the DB is given a GUID
Client View
Client module that adds menu item 'Mail' to the client navbar
When clicking this menu item, a page loads that displays a table. This table shows all of the entries of file uploads from the admin view. The table should have an image of the scanned mail, the day/time received, and another column that will be blank for now.
So that's what I'm trying to accomplish. In an effort to understand structure of Prefex CRM modules better, I deconstructed the Prefex CRM Employee Chat module. It's hard to compare apples to oranges in this case, but it did help me to develop a file structure which is as follows:
-assets
--css
--js
--module_includes
-controllers
--admin_controller
--client_controller
-models
-uploads
-views
--admin_view
--client_view
mail.php
index.php
install.php
Now that you have an understanding of what I'm doing this is where I need assistance-
Where I'm stuck: I'm looking to recycle the file upload feature that is already built inside of Prefex CRM. Where the file is stored normally is fine and does not need to be changed. I'm unsure of how to reuse these built in functions to create the Mail_ClientsController.php and Mail_Controller.php, as well as some uncertaintly on the mail_admin_view.php, and mail_clients_view.php
Could anyone share some examples of some working modules for Perfex that could shed some light on how to connect these?
mail.php page
<?php
/**
* Ensures that the module init file can't be accessed directly, only within the application.
*/
defined('BASEPATH') or exit('No direct script access allowed');
/*
Module Name: Mail
Description: Client online mailbox module for Perfex CRM system
Version: 2.3.0
Requires at least: 2.3.*
*/
define('BSSI_MAIL_MODULE_NAME', 'bssi_mail');
define('BSSI_MAIL_MODULE_UPLOAD_FOLDER', module_dir_path(BSSI_MAIL_MODULE_NAME, 'uploads'));
$CI = &get_instance();
/**
* Register the activation
*/
register_activation_hook(BSSI_MAIL_MODULE_NAME, 'bssi_mail_activation_hook');
/**
* The activation function
*/
function bssi_mail_activation_hook()
{
require(__DIR__ . '/install.php');
}
/**
* Register new menu item in admin sidebar menu
*/
if (staff_can('view', BSSI_MAIL_MODULE_NAME)) {
if (get_option('bssi_staff_can_delete_messages') == '1') {
$CI->app_menu->add_sidebar_menu_item('bssi_mail', [
'name' => 'BSSI Mail',
'href' => admin_url('bssi_mail/mail_admin_view'),
'icon' => 'fa fa-envelope',
'position' => 6,
]);
}
}
Mail_ClientsController.php (unsure of which functions to put here for upload feature)
<?php defined('BASEPATH') or exit('No direct script access allowed');
class Prchat_ClientsController extends ClientsController
{
}
Mail_Clients_View.php
<?php defined('BASEPATH') or exit('No direct script access allowed'); ?>
<div class="bssiClient">
<div class="container">
<div class="row">
<div class="col">
<table class="bssiMailTable">
<thead>
<th>Mail Image</th>
<th>Date Received</th>
<th>Actions</th>
</thead>
<tr>
<td>Image Query</td>
<td>Get Date Query</td>
<td>Action Items</td>
</tr>
</table>
</div>
</div>
</div>
</div>
Mail_admin_view.php
<?php defined('BASEPATH') or exit('No direct script access allowed'); ?>
<div class="bssiAdmin">
<div class="container">
<div class="row">
<div class="col">
<table class="bssiAdminMailTable">
<thead>
<th>Mail Image</th>
<th>Date Received</th>
<th>Actions</th>
</thead>
<tr>
<td>Image Query</td>
<td>Get Date Query</td>
<td>Action Items</td>
</tr>
</table>
</div>
</div>
</div>
</div>

So in your controller/model you would need to load in the standard email model within your construct method. Perfex has a standard model it uses for distributing emails (can be seen under root > application > models > Emails_model.php)
$this->load->model('emails_model');
or if it's being called from outside of the admin controller (e.g. via a cron)
$this->ci->load->model('emails_model');
Within the standard Emails_model.php there is a function "send_simple_email()" which will allow you to send an email to any email address directly from Perfex
E.G.
$email = 'your_email#email.com';
$subject = 'Email Subject';
$message = 'Your Message';
$this->ci->emails_model->send_simple_email($email, $subject, $message);
For file upload, you should be looking at the standard file upload procedure within Perfex (take a look inside upload_helper.php, and you'll find a number of functions which will help you get a file uploaded.

Related

React js along with PHP (Yii2 framwork )

I am a newbie to react js. I already have a project running on yii2 framework with frontend in traditional way ( Html , css ) but now need to run the frontend code using js.
I tried to include react files in AppAsset class like following
public $js = ["https://unpkg.com/react#15.1.0/dist/react.min.js","https://unpkg.com/react-dom#15.1.0/dist/react-dom.min.js","https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.23/browser.min.js","https://unpkg.com/babel-standalone#6.15.0/babel.min.js"];
and placing simple code in index.php
<div class="site-index">
<div id="helloWorld"> </div>
</div>
<script type="text/babel">
class HelloWorld extends React.Component{
render() {
return(
<div className='jumbotron text-center'>
<h1> Welcome </h1>
<p> Welcome to My Yii project powered by React Js </p>
</div>
) ;
}
}
ReactDOM.render(<HelloWorld></HelloWorld>,document.getElementByid('helloWorld'));
</script>
with no success. It just simply create a div site-index without actually rendering the render function of helloworld class.
I also tried to include all the react js to my index file but still the outcome is same. I guess i am missing something on how to include the js files and that's why my render is not working.

Partial Views in CodeIgniter

I am a beginner in using CodeIgniter Framework. Previously, I have learned Laravel. and my problem is I want to make dynamic template like Blade in Laravel. So, in every pages I just load the style and script that only needed by that page.
Here is the code, that I created with CodeIgniter so It could be dynamic to load custom style and custom script.
template.php
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
// <hmtl>
$this->load->view($header);
if(isset($style))
$this->load->view($style);
// <body>
$this->load->view($navbar);
if(isset($sidebar))
$this->load->view($sidebar);
$this->load->view($content);
$this->load->view($footer);
// </body>
if(isset($script))
$this->load->view($script);
// </html>
and my controller
public function index()
{
$data = [
'title' => 'Home',
'header' => 'partials/_header',
'navbar' => 'partials/_navbar',
'content' => 'guest/public',
'footer' => 'partials/_footer'
];
$this->load->view('template', $data);
}
maybe you have better thought, because I am stuck with it. in Laravel it's easy because there is #yield and #section. any ideas from you guys, would be so helpful to me, thank you.
finally, I just figured it out the best way make it dynamic. how to load custom script and css in every different pages.
here is the code for template.php (inside views folder)
<?php
defined('BASEPATH') OR exit('No direct script access allowed');
$this->load->view($header);
$this->load->view($navbar);
$this->load->view($content);
$this->load->view($footer);
and the controller controller
public function index() {
$data = [
'header' => 'partials/_header',
'style' => 'partials/style/_public_css',
'navbar' => 'partials/_navbar',
'content' => 'guest/public',
'footer' => 'partials/_footer',
'script' => 'partials/script/_public_js'
];
$this->load->view('template', $data);
}
and in the partials view of _header.php
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>...</title>
<!-- Partial CSS Here -->
<?php if(isset($style)) $this->load->view($style); ?>
</head>
<body>
_navbar.php
<header>
<nav class="navbar navbar-inverse navbar-fixed-top">
....
</nav>
</header>
then the content variable in controller, it loads public.php (in my case, you have to replace with any pages you want to load)
<div class="container">
....
</div>
and the last one is _footer.php
<footer>
....
</footer>
<!-- JQuery HERE -->
<!-- any js that you will you in all pages HERE -->
<!-- Partial Script Here -->
<?php if(isset($script)) $this->load->view($script); ?>
</body>
<html>
Remember, if your footer does static in every pages place your JQuery in _footer.php and if it doesn't just place the jquery in the _header.php even it's not the best practice to load the script first.
I did something similar once, sometime ago admittedly now, but I did it all in a template library.
Using setters like
$this->template_library->set_css_script('page.css');
$this->template_library->set_layout('product_page');
The controller would end with a call like:
$this->template_library->render_page();
The template library would then use the load->view functions to create the page and output it depending on the values that were set or not set, and the page layout meant I could have various set layouts like home_page, product_page, checkout_page, message_page etc etc.
For the layouts, I had one master layout that did the main page, and variations for the different pages.
In the end though I reverted to simple views, with common files for header and footer and any variants. It was just easier to maintain lots of different view files than it was to maintain all the layouts and templates and partials.
One thing that helps a lot is that a view can load another view. So for the sake of keeping everything DRY, this means that any derivative page part views can be kept in a 'partials' folder for things like 'related products' or 'blog_list' etc.
Hope that helps.

How can I customize prototype widget templates for a single property?

In my application, I have classes A and B. Objects of class A own many objects of class B.
To edit these objects, I have a compound form. The outer form edits the properties of object A and the inner form edits all the owned instances of B. This subform is supposed to display its entries as table rows. The table itself is defined by the outer form.
My project is using the PHP templating engine. So far, I have managed to overwrite the template widget to edit an object of type B. The property of A holding all instances of B is rendered as collection into the form. This means the following templates are rendered: collection_widget.html.php -> form_widget_compound.html.php -> form_rows.html.php -> form_row.html.php ->
my_custom_template_widget.html.php
However, some of these templates add tags to surround the templates they are rendering which destroys my table layout. I have managed to fix this by overwriting the template for this property by creating _formForA_propertyB_widget.html.php and rendering everything manually in there.
The problem I have now is that it should be possible to add objects to this collection. I want to do this using the prototype functionality provided by Symfony. However, it seems the prototype is not created using my overwritten template (of course not, as this is for a collection and not for a single row) but instead is created using form_row.html.php. I have tried overwriting this by creating _formForA_propertyB_form.html.php but this did not make any difference.
How can I overwrite the prototype template for this specific property?
Essentially this question is very similar to How to customize the data-prototype attribute in Symfony 2 forms but this one is about using PHP as a templating engine. Answers on the other question use features of the TWIG templating engine which are not available with the PHP engine.
Sample code to illustrate the problem:
Views/EditA.html.php:
<table data-prototype="<?php echo $view->escape($view['form']->row($form['collectionOfB']->vars['prototype'])) ?>">
<thead>
<tr>
<th>Description</th>
<th>Prop1</th>
<th>Prop2</th>
</tr>
</thead>
<tbody>
<?php echo $view['form']->widget($form['collectionOfB']) ?>
</tbody>
</table>
Views/Form/_objectA_collectionOfB_widget.html.php:
<?php foreach ($form as $child) : ?>
<?php echo $view['form']->widget($child) ?>
<?php endforeach; ?>
Views/Form/objectB_widget.html.php:
<tr>
<td><?php echo $view['form']->widget($form['description']) ?>
<?php echo $view['form']->errors($form['description']) ?></td>
<td><?php echo $view['form']->widget($form['prop1']) ?>
<?php echo $view['form']->errors($form['prop1']) ?></td>
<td><?php echo $view['form']->widget($form['prop2']) ?>
<?php echo $view['form']->errors($form['prop2']) ?></td>
</tr>
As I said, the form is rendered correctly, but this is the prototype:
<div>
<label class="required" >__name__label__</label>
<tr>
<!-- snip more code here -->
</tr>
</div>
You can see that this contains the label and a div, both of which I do not want as it will destroy the table.
It turns out that the answer is way simpler than I thought. Instead of rendering the entire row (and thereby rendering the form_row.html.php template containing a div) I need to render the widget only.
Basically all you need to do is replace
$view->escape($view['form']->row($form['collectionOfB']->vars['prototype']))
with
$view->escape($view['form']->widget($form['collectionOfB']->vars['prototype']))

Codeigniter : Protect folder from direct access

Hello guys I have a small project connected with a database.I own a function for
uploading files into a folder and also save files path to the database.
In my index page I read files path from database and output a table with links to these files for downloading.
Everything works fine and files are able to be downloaded unless,
the problem is that I forgot to secure this folder and yesterday realized that I should protect it somehow because people can download files directly with links
and I need to check if user is logged to be able to download it.
So my question is:
How to protect the folder with these files from direct access and make only logged users
to be able to download files from this folder
My upload path is ./uploads/ inside this folder I had htaccess file
order deny,allow
deny from all
In controller I have
public function viewAllPersons()
{
if($this->ion_auth->logged_in())
{
if(!$this->ion_auth->in_group(1)){
show_404();
}
else {
$data = array();
$data['persons'] = $this->get_persons(); // get all persons from database as array
$this->load->view('admin/header_view');
$this->load->view('admin/persons_view',$data); // pass data to the view
$this->load->view('admin/footer_view');
}
} else {
redirect(base_url());
}
}
My view file contains this
{
<div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
<h1 class="page-header"><span class="glyphicon glyphicon-th-list"></span> Archive</h1>
<h2 class="sub-header pull-left">All records db</h2>
<span class="glyphicon glyphicon-plus-sign"></span> Add new record
<form class="navbar-form navbar-right" method="post" action="<?=site_url('dashboard/persons');?>" name="searchform" >
<div class="form-group">
<input type="text" id="search" name="search" class="form-control" placeholder="" autocomplete="off">
</div>
<button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-search"></span></button>
</form>
<div class="clearfix"></div>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>Firstname</th>
<th>Middlename</th>
<th>Lastname</th>
<th>ID</th>
<th>Filename</th>
<th>Data</th>
<th>Options</th>
</tr>
</thead>
<tbody>
<?php
$counter = 1;
foreach($persons as $person) { ?>
<tr>
<td><?=$person['person_id'];?></td>
<td><?=$person['first_name'];?></a></td>
<td><?=$person['middle_name'];?></td>
<td><?=$person['last_name'];?></td>
<td><?=$person['personal_number'];?></td>
<td><?=$person['document_path'];?></td> <!-- show links to files for each row !-->
<td><?=$person['created_on'];?></td>
<td>
<a href="<?=base_url('/dashboard/persons/edit/'.$person['person_id'])?>">
<span class="glyphicon glyphicon-pencil edit-icon"></span>
</a>
</td>
</tr>
<?php $counter++; } ?>
</tbody>
</table>
<div class="row">
<?php if(isset($links)) {
echo $links;
}?>
</div>
</div>
</div>
<?php } ?> }
Here is my problem when I output links to files I need to check if user is logged before to be able to download files using the links saved in database
Example of project -- picture
Because people can download files with direct link
Example
http://website.com/uploads/document.docx
Once I have htaccess file I`m unable to download a file need maybe a function to rewrite rules or
to give access to logged users somehow
I also tried a download helper from codeigniter but download files only if I remove the htaccess rules If rules exist inside htaccess file download helper is unable to download the file.
Thanks in Advance!
You have a few possibilities, the simplest one would be to have control of the access of these folders with a Controller.
You need a file table with minimum : id, path.
Let's say user A wants file ABC.jpg (with the id of 1337) : Instead of serving him http://example.com/uploads/ABC.jpg, you give him http://example.com/files?id=1337.
This route calls the index of controller Files and in the index you can do this pseudo-code :
function index() {
//Check if logged in
if (!$user->logged()) {
redirect('/404');
}
//Get file from database
$file = $this->db->query('SELECT * FROM file WHERE id='.$this->input->get("id"))->result();
//Then serve the file
header("Content-type: image/jpeg");
readfile($file->path);
}
EDIT :
I will try to explain it in other terms :
Create a table of uploaded files called file. Something like
CREATE TABLE file (id INT NOT NULL AUTO_INCREMENT, path VARCHAR(100) NOT NULL, PRIMARY KEY ( id ))
Update your person table so that it doesn't have the document_path but file_id instead. And when you upload a file, you save it's path in the table file then assign the file id to the person (in table person of course).
Instead of <?php echo base_url('/uploads/'.$person["document_path"]);?>, you need to do <?php echo base_url('/file?id='.$pseron['file_id']);?>
This is because we want the user to go to a specific controller that you need to create File.php (the controller).
In this controller, the function index (the default function of the controller File) must do something like I showed you before the edit. It means you retrieve from the database the file path based from the file id, then you serve the file. This is called PHP serving instead of Apache (default) serving of files.
I was facing the same problem because my files were directly accessed by the users. especially uploads files and images. I was working on a PHP framework.
I simply added one line of code in the .htaccess file. and it was done.
If you don't have one in your WEBSITE FOLDER then create a .txt file and name it as .htaccess (if you are not using any framework).
then open the .htccess file and simply write: Options -Indexes
NOTE: DON'T PUT .htaccess file in any folder just simply open your website folder in htdocs and create .htaccess

404 page not found Codeigniter Controller

I have a simple Codeigniter application.
Its default controller is login. When the application opens in a browser it loads the default controller and its view. But when I'm going to open another controller function, its showing 404 page not found.
This application works fine on my local PC. But on the Client Live Server this problem occurs. Client server is using Ubuntu 12.04.
Sample code
class Login extends CI_Controller{
function __construct(){
parent::__construct();
}
function index(){
$this->load->view('login/index');
}
}
View file:
<table>
<tr>
<td>Username: </td>
<td><?php form_input('txt_username',set_value('txt_username',isset($row->username)?$row->username:''));?> </td>
</tr>
<tr>
<td>Username: </td>
<td><?php form_password('txt_username',set_value('txt_username',isset($row->password)?$row->password:''));?> </td>
</tr>
<tr>
<td colspan=2>for register click
<a href=<?php echo site_url('registers/index');?>>Register</a></td>
</tr>
</table>
Register Controller:
class Registers extends CI_Controller{
function __construct(){
parent::__construct();
}
function index(){
$this->load->view('register/index');
}
}
When I click on Register link or other link in Menu showing 404 not found.But in my pc it is working fine.
Probably your Rewrite rules are not correct.
You can check two options. First: check whether your Rewrite modules is enable or not. Second: check your .htaccess file.
I am strongly recommend to check the second option. Remember your .htaccess file will vary based on hosting server.
In login view you have
<a href=<?php echo site_url('registers/index');?>>Register</a></td>
here link has 'registers' note last 's' and your controller is 'register'
This is a common mistake :)

Categories