How to set & lock SiteTree in Silverstripe 4? - php

We're working on a project where Silverstripe acts as headless CMS with a single API data point.
The content is all from non-SiteTree dataobjects & the API data point is the only SiteTree record we need.
What is the best way of making sure the API data point exists & it is the only SiteTree record on each /dev/build. We could then disable PagesAdmin in LeftAndMain so users couldn't edit/ break it.
I've found code here which would look a bit like this for our case:
$api = new API/AccessPoint();
$api->Title = 'API';
$api->URLSegment = 'home';
$api->ShowInMenus = '1';
$api->Version = '1';
$api->ParentID = '0';
$api->write();
$api->doRestoreToStage();
But I'm not sure of the correct approach for making sure that a dev\build removes all the other pages & creates 1 record of this page.
Any help would be appreciated.

You can use requireDefaultRecords() in your DataObject to create records on a dev/build. You'll need to do some kind of check before creating a new one though, e.g.
public function requireDefaultRecords()
{
parent::requireDefaultRecords();
if (AccessPoint::get()->filter('URLSegment', 'home')->exists()) {
return;
}
// create your new object here
}

Related

Automatic Laravel routing for static pages

I have to maintain a site for a client, they had it made with Laravel, the most frequent requests from them are to create new static pages and the more I create them - the more I feel there are definitely better ways to implement them.
To create a static page I go to the admin panel, a menu "Static Pages", push a button "Create New" and there create an entry that goes into a database table. To make the static page show in the website I have to define it in a controller called "FrontEndController" like this:
public function some_page() {
$page = StaticPages::find(1);
return view('frontend.static_pages.some_page', compact('page'));
}
public function some_other_page() {
$page = StaticPages::find(2);
return view('frontend.static_pages.some_other_page', compact('page'));
}
...
Then define routes like this:
Route::get('some-page', 'FrontEndController#some_page')->name('static_page.some_page');
Route::get('some-other-page', 'FrontEndController#some_other_page')->name('static_page.some_other_page');
Now I always thought that you create an admin panel with a menu "Static Pages" and a button "Create New" so that you don't have to put any code manually, but seemingly the developer had other ideas...
So my question is how do you refactor a code like this so that you don't have to go through all of the repetitive process in any similar scenario and write code manually?
Btw I may need to sometimes send some generic params to different static pages and I want to keep the URLs the same as they are. Please, keep in mind that I'm not a very advanced user of Laravel or even PHP.
There is no need to add extra method and router for per page manually.
I think that is a matter of unexperienced developer ,
So, You need to refactor your codes like this.
Add one router and remove others.
Route::get('/static/{id}','FrontendController#index');
On your Controller.
public function index($id)
{
$page = StaticPages::find($id);
$theme = $page->theme; //assume you have save your html themplate name in your table via theme column
return view('frontend.static_pages.'.$theme, compact('page'));
}
Save url or slug in your database
Route::get('staticpage/{pagename}', 'FrontEndController#MethodName');
$page = StaticPages::where('url',$url)->first();
return view('YourStaticPage', compact('page'));

Make model dynamically using user supplied model name in laravel

I am stuck with it and i couldn't find any appropriate solution for this. what i want to achieve is in my admin panel based upon check box value i want to change active status of specific control and update database value using ajax. I want to make a common ajax function in controller to avoid repeatedly writing same ajax function for other controls like menu manager content manager, documents manager etc.So i want to send Model name to the ajax controller so that same function can be used. Ajax call is working perfectly but couldn't make appropriate models. for example:
$m = new App\Model.$request->model OR $m = 'App\Model\'.$request->model (adding last \ gives an error) or answer provided in Dynamically use model in laravel is not helping either. Is there any better ways if yes please suggest. I can do this below but it is hardcoded so i want to make model dynamic models
if($request->model ==='Menu')
$model = new \App\Http\Models\Menu;
else if($request->model === 'News')
$this->model = new \App\Http\Models\News;
else if($request->model === 'Document')
$this->model = new \App\Http\Models\Document;
Thankyou !!!
You can just use:
$modelName = '\\App\\Http\\Models\\'.$request->model;
$this->model = new $modelName;
However you should add validation to make sure only some allowed models would be used or at least do something like this:
if (! in_array($request->model, ['Menu', 'News', 'Document']))
{
throw new \Exception('Invalid model');
}
$modelName = '\\App\\Http\\Models\\'.$request->model;
$this->model = new $modelName;
This is because you don't want to expose probably all the models data for security reasons.
Try the below code
if($request->model){
$m = '\App'. '\' .$request->model;
//other code
}

How do I change codeigniter existing login system using 3rd party authentication system

I really need help in making modifications to a script I purchased which was designed using codeigniter (a system I am totally new to). The project is designed to have only two user roles with fixed permission (admin, others(is_logged_in)). After couple of hours of learning how MVC works I have been able to change so little yet insignificant stuff in project.
My big problem is this:
I want to use the script to complete a web POS app which I have been working on basically in native php, the project uses ion-auth for the login systems and authentications, please I want to use another 3rd party acl systems like flexiauth, oauth, Aauth, etc but I don't have enough knowledge to know what files I will be replacing and which controller (s) I will need to made modification in.....I am totally stuck....please help me
What I need is simple enough:
I want to have multiple groups and users with access to different resources in the web app e.g a cashier (should have access to pos, customer, report daily_sales, close register, print invoice) AND (an account should have access to dashboard, reports, order etc), manager should be able to create new user, view sales, void sales etc, AND admin should of course have overall access.
What I have now is admin(full access to all the resources) other logged_in users: restricted in some areas.
Groups I have is 2:
Admin
Staff.
I don't know how to continue.
i think i find the custom library used to define the access
Please check the follow code and advice on where i can start:
class MY_Controller extends CI_Controller {
function __construct() {
parent::__construct();
define("DEMO", 0);
$this->Settings = $this->site->getSettings();
$this->lang->load('app', $this->Settings->language);
$this->Settings->pin_code = $this->Settings->pin_code ? md5($this->Settings->pin_code) : NULL;
$this->theme = $this->Settings->theme.'/views/';
$this->data['assets'] = base_url() . 'themes/default/assets/';
$this->data['Settings'] = $this->Settings;
$this->loggedIn = $this->tec->logged_in();
$this->data['loggedIn'] = $this->loggedIn;
$this->data['categories'] = $this->site->getAllCategories();
$this->Admin = $this->tec->in_group('admin') ? TRUE : NULL;
$this->data['Admin'] = $this->Admin;
$this->m = strtolower($this->router->fetch_class());
$this->v = strtolower($this->router->fetch_method());
$this->data['m']= $this->m;
$this->data['v'] = $this->v;
}
function page_construct($page, $data = array(), $meta = array()) {
if(empty($meta)) { $meta['page_title'] = $data['page_title']; }
$meta['message'] = isset($data['message']) ? $data['message'] : $this->session->flashdata('message');
$meta['error'] = isset($data['error']) ? $data['error'] : $this->session->flashdata('error');
$meta['warning'] = isset($data['warning']) ? $data['warning'] : $this->session->flashdata('warning');
$meta['ip_address'] = $this->input->ip_address();
$meta['Admin'] = $data['Admin'];
$meta['loggedIn'] = $data['loggedIn'];
$meta['Settings'] = $data['Settings'];
$meta['assets'] = $data['assets'];
$meta['suspended_sales'] = $this->site->getUserSuspenedSales();
$meta['qty_alert_num'] = $this->site->getQtyAlerts();
$this->load->view($this->theme . 'header', $meta);
$this->load->view($this->theme . $page, $data);
$this->load->view($this->theme . 'footer');
}
}
Codeigniter doesn't come with native login system, so the script you purchased is already using a third party package/plugin.
Look for login script code in the following locations : Models, Libraries.
The controller is where you control everything, so you can have a look at that later, first you need to determine which files are being used as the core of login functionalities. Once you have determined, you can look at the code and understand how they are handling user groups/ previlages etc.
About the groups and previlages, either they have their on table in database where the values are stored for admin, public etc or the values are stored in a config file, you can find all the config files in the application\config directory. Use PHPMYAdmin to check database and check non codeigniter config files too.
Check the Auth in every controller. Remove them and put your exiting auth system.

Reduce database calls for php web shop

I'm looking for a way to prevent repeated calls to the database if the item in question has already been loaded previously. The reason is that we have a lot of different areas that show popular items, latest releases, top rated etc. and sometimes it happens that one item appears in multiple lists on the same page.
I wonder if it's possible to save the object instance in a static array associated with the class and then check if the data is actually in there yet, but then how do I point the new instance to the existing one?
Here's a draft of my idea:
$baseball = new Item($idOfTheBaseballItem);
$baseballAgain = new Item($idOfTheBaseballItem);
class Item
{
static $arrItems = array();
function __construct($id) {
if(in_array($id, self::arrItems)){
// Point this instance to the object in self::arrItems[$id]
// But how?
}
else {
// Call the database
self::arrItems[id] = $this;
}
}
}
If you have any other ideas or you just think I'm totally nuts, let me know.
You should know that static variables only exist in the page they were created, meaning 2 users that load the same page and get served the same script still exist as 2 different memory spaces.
You should consider caching results, take a look at code igniter database caching
What you are trying to achieve is similar to a singleton factory
$baseball = getItem($idOfTheBaseballItem);
$baseballAgain =getItem($idOfTheBaseballItem);
function getItem($id){
static $items=array();
if(!isset($items[$id])$items[$id]=new Item($id);
return $items[$id];
}
class Item{
// this stays the same
}
P.S. Also take a look at memcache. A very simple way to remove database load is to create a /cache/ directory and save database results there for a few minutes or until you deem the data old (this can be done in a number of ways, but most approaches are time based)
You can't directly replace "this" in constructor. Instead, prepare a static function like "getById($id)" that returns object from list.
And as stated above: this will work only per page load.

Multiple pages with codeigniter?

I am trying to find the best way to only have to load my view one time and re-use them on different pages.
For the home page for example I have this code:
function index()
{
/* Load Includes for all pages */
$header = $this->load->view('includes/header','',true);
$scripts = $this->load->view('includes/scripts','',true);
$navigation = $this->load->view('includes/navigation','',true);
$footer = $this->load->view('includes/footer','',true);
/* Load widgets for Home Page*/
$rotator = $this->load->view('widgets/home_feature','',true);
$login = $this->load->view('widgets/login','',true);
$cal = $this->load->view('widgets/calendar_home','',true);
$gallery = $this->load->view('widgets/photos_scroll','',true);
$tags = $this->load->view('widgets/tags_view','',true);
$spotlight = $this->load->view('widgets/spotlight','',true);
$recent = $this->load->view('widgets/activityfeed','',true);
$data=array(
'title'=>'Philly2Night.com',
'MetaDesc'=>'Cities2Night new social network',
'MetaKeywords'=>'Social, Party, Plan, Events',
//Load Includes
'header'=>$header,
'scripts'=>$scripts,
'navigation'=>$navigation,
'footer'=>$footer,
//Load Widgets
'feature'=>$rotator,
'login'=>$login,
'calendar'=>$cal,
'photos'=>$gallery,
'tags'=>$tags,
'spotlight'=>$spotlight,
'recent'=>$recent
);
$this->load->vars($data);
$this->load->view('pages/home_view');
}
How do I create new pages, but referencing these views? I tried making the var global, ideally I want to use switch, and define cases but that alas did not work either.
If I understand correctly, I think you just want to have one common place for all the load code, so that you do not have to copy/paste that part for each action in the controller. If that's the case...
Create a constructor in your controller, move the load->views there, and store them into variables inside the class:
function __construct() {
parent::__construct();
/* Load Includes for all pages */
$this->header = $this->load->view('includes/header','',true);
$this->scripts = $this->load->view('includes/scripts','',true);
$this->navigation = $this->load->view('includes/navigation','',true);
$this->footer = $this->load->view('includes/footer','',true);
}
Be sure to change any $header, $scripts, etc references to $this->header, $this->scripts, etc.
Also, replace __construct with your class name if you're using PHP4.
First of all you shouldn't be loading so many pages. Each file system request takes it's toll on performance. Rather than having "header" and "footer" just combine them into the "home_view" page.
Second, your question sounds like you are stating that once you load the views you want them to remain loaded for each page request afterward. That isn't possible with PHP as each request is a whole new load. However, if you are doing a lot of database queries or calculations and then loading widgets you can cache the widgets for 5 mins or so and save the queries each page. Look in the CodeIgniter forums for cache classes.
This may or may not be of some use:
http://codeigniter.com/forums/viewthread/77279/
I use this on ALL of my CodeIgniter projects, it makes templating very very easy.

Categories