Is there a way to create objects/ table entries during the extension installation in TYPO3? - typo3

I want to create objects during the installation of an extension. For example I have the following two simple domain models:
class Product extends AbstractEntity
{
protected $name = '';
protected $sku = '';
...
}
class Location extends AbstractEntity
{
protected $name = '';
protected $city = '';
...
}
and a third domain model like:
class Mapper extends AbstractEntity
{
protected $domainModelName = '';
protected $domainModelProperty = '';
}
Now I want too add entries like this:
domain_model_name | domain_model_property
Product | name
Product | sku
Location | city
....
during the extension installation or directly after the installation, so that the tx_foxexample_domain_model_mapper table will be filled automatically, is this possible?
I know that I can use a initializeAction, but then the entries will only be generated if I add a plugin and visit the page etc., but I want that the entries/ objects already exists before I use a plugin or add some objects.

You can store your static data in the file ext_tables_static+adt.sql which must be located in the root folder of your extension.
According to the TYPO3 API, you must should use the following command to export your static data
mysqldump --password=[password] [database name] [tablename] --add-drop-table > ./ext_tables_static.sql
Also make sure, that the table structure of static tables is present in the ext_tables.sql file.
The extension static_info_tables makes use of this technique. You can have a look at the extension here for more details.

Related

Eloquent relationship returns null, but a similar one is fine

Using Lumen 5.5.2 and illuminate/database v5.5.17.
I have 3 models set up, where one belongs to the other 2. So Quote, has an area, and a depot.
The relationship with the depot works as expected, the area returns null.
for example
$quoteModel = new Quote();
$quote = $quoteModel
->with('area')
->with('depot')
->where('id', '=', $id)
->first();
echo 'depot id : ' , $quote->depot->id , "<br>\n";
echo 'area id : ' , $quote->area->id , "<br>\n";
The depot id will be echoed, the area will cause an error because it is not an object.
Passing the models names as an array ->with(['area', 'depot']), or just requesting area (either method) does not fix it.
Quote.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Quote extends EloquentModel {
protected $table = 'quotes';
public function area() {
return $this->belongsTo('\App\Models\Area', 'area_id', 'id');
}
public function depot() {
return $this->belongsTo('\App\Models\Depot', 'depot_id', 'id');
}
}
Area.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Area extends EloquentModel {
protected $table = 'areas';
public $timestamps = false;
public $incrementing = false;
public function quotes() {
return $this->hasMany('\App\Models\Quote', 'area_id', 'id');
}
}
Depot.php
namespace App\Models;
use Illuminate\Database\Eloquent\Model as EloquentModel;
class Depot extends EloquentModel {
protected $table = 'depots';
public $timestamps = false;
public $incrementing = false;
public function quotes() {
return $this->hasMany('\App\Models\Quote', 'depot_id', 'id');
}
}
If I create a parse error in Area.php the script will fail, proving it is being included.
I have a listener set up so I can log the queries, and they show up just fine.
select * from `quotes` where `id` = 99192 limit 1
select * from `areas` where `areas`.`id` in (072)
select * from `depots` where `depots`.`id` in (07)
If I run the area query manually it returns the row I expect.
I tried changing the name of the area relationship, and it doesn't help.
So the missing piece of the puzzle, was that this project is setup up against a legacy database as part of updating an existing web app.
Turns out that there was some datatype inconsistency; I found this out when I could successfully link another model to area with no issues. The field for the area_id is normally a zero filled int, but for some reason on the quotes table it was a char; so the data looked correct when browsing in adminer, and worked when copied and pasted, but did not match up somewhere in Eloquents internals.
Changing the datatype on the table fixes the issue.

How to integrate web services with custom module in SugarCRM?

I'm using SugarCRM to develop a software for customers management. I created a custom module from basic template with custom fields. Is it possible to get rid of SugarCRM db and perform CRUD operations through external web serivices? Actually I was able to show web services data in the datailview by setting the bean property of a custom controller.
class CustomerController extends SugarController{
public function action_detailview(){
$customer = new Customer();
$customer = getCustomerFromWebService();
$this->bean = $customer;
$this->view = "detail";
}
}
I would like to do the same thing with listview, but I don't know how set the records of the list (if it exists) used by the default listview.
You can change list view by customizing view.list.php in custom/modules/modulename/views/view.list.php using following code:
<?php
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
require_once('include/MVC/View/views/view.list.php');
// name of class match module
class modulenameViewList extends ViewList{
// where clause that will be inserted in sql query
var $where = 'like 'htc'';
function modulenameViewList()
{
parent::ViewList();
}
/*
* Override listViewProcess with addition to where clause to exclude project templates
*/
function listViewProcess()
{
$this->lv->setup($this->seed, 'include/ListView/ListViewGeneric.tpl', $this->where, $this->params);
echo $this->lv->display();
}
}
?>

Inheritance of TYPO3 models

I have a tricky question about the inheritance of TYPO3 models:
I want to extend the extension powermail with two seperate/independed (!) extensions. The first extend powermail TCA-forms and needs the new fields in the fluid template. The second extends also the TCA-forms, but not need an output in the frontend.
Now I use the mixed-ins hack from Franz Koch http://lists.typo3.org/pipermail/typo3-project-typo3v4mvc/2010-September/006497.html which using the delete field as record type. But this solution works only for one extension. According to the loading of the TS persistence settings either the first or the second model of the extension will be loaded.
If I use an own field for the record type – eg. for the field record of powermail – I can use only one record type for the one extension, but can't access to the other.
Is there a way to "merge" ALL models related to the base model?
Next current TS config:
config.tx_extbase {
persistence {
classes {
# Using mixed-ins hack from Franz Koch to make map table extendable.
# #see http://lists.typo3.org/pipermail/typo3-project-typo3v4mvc/2010-September/006497.html
Tx_Powermail_Domain_Model_Fields {
mapping.recordType = 0
subclasses.0 = Vendor\MyExtension\Domain\Model\Powermail\Fields
}
Vendor\MyExtension\Domain\Model\Powermail\Fields {
mapping {
tableName = tx_powermail_domain_model_fields
recordType = 0
columns {
tx_myfirstextension_field_one.mapOnProperty = FieldOne
}
}
}
}
}
}
ext_tables.php:
// Using mixed-ins hack from Franz Koch to make map table extendable.
// #see http://lists.typo3.org/pipermail/typo3-project-typo3v4mvc/2010-September/006497.html
$TCA['tx_powermail_domain_model_forms']['ctrl']['type'] = 'deleted';
$TCA['tx_powermail_domain_model_pages']['ctrl']['type'] = 'deleted';
$TCA['tx_powermail_domain_model_fields']['ctrl']['type'] = 'deleted';

How can I selectively apply a VSTemplate?

I am creating a custom VSTemplate for MVC 4 applications for my company that uses a wizard that is comparable to the wizard that appears when you create a new MVC4 application. I have one of two templates I would like to apply when the developer creates a new app of this type as shown here:
Both of those entries correspond to templates that are defined inside my VSIX project under a folder called ProjectTemplates:
My question is, how do I apply the correct template when the wizard runs? I know how to create a vstemplate with multiple projects (using the ProjectCollection node in the vstemplate), but that's not really what I want to do since they will never be deployed together. I see that I can add both vstemplates as Assets to my vsixmanifest file, but I'm not really sure how to apply just one template conditionally.
Thanks!
You'll need to include the files for your "optional" template(s) in sub directories of the the "root" template folder but EXCLUDE them from the TemplateContent Element of the "root" template.
Your IWizard implementation needs to keep a reference to the EnvDTE.DTE object (the first parameter of RunStarted) and use it in the ProjectFinishedGenerating to add the projects to the solution using the template(s) that match what the user selected.
public class SelectTemplatesWizard : IWizard
{
private EnvDTE.DTE _dte = null;
private string _solutionDir = null;
private string _templateDir = null;
public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
{
// Store the reference to the environment for later use
_dte = automationObject as EnvDTE.DTE;
/*
The value of the item in the replacements dictionary for the key
$destinationdirectory$ is populated with the physical location of
the directory (named based on the user entered project name) created
sibling to the solution file.
The solution directory will be this directories parent
when the Type attribute of the VSTemplate element is ProjectGroup
*/
_solutionDir = System.IO.Path.GetDirectoryName(replacementsDictionary["$destinationdirectory$"]);
// customParams[0] is a default custom param that contains the physical location of the template that is currently being applied
_templateDir = System.IO.Path.GetDirectoryName(customParams[0] as string);
}
public void ProjectFinishedGenerating(Project project)
{
int userSelected = 1;
string name= null, projectPath= null, templatePath = null;
switch (userSelected)
{
case 0:
{
name = "Angular";
projectPath = System.IO.Path.Combine(_solutionDir, "Angular");
templatePath = System.IO.Path.Combine(_templateDir , "Angular\Angular.vstemplate");
}
break;
case 1:
{
name = "MVC4";
projectPath = System.IO.Path.Combine(_solutionDir, "MVC4");
templatePath = System.IO.Path.Combine(_templateDir , "MVC4\MVC4.vstemplate");
}
break;
}
_dte.Solution.AddFromTemplate(templatePath, projectPath, name);
}
/* Other IWizard methods excluded for brevity */
}

cakephp and mongodb - relationships

i have a question on mongodb, model cakephp and relationships.
I'd create the following relations:
User -> hasMany -> City
City -> belongsTo -> User
In MongoDB, I have two tables:
users
cities (with key user_id)
In cakephp, I have 2 model:
User.php
class User extends Model {
public $name = 'User';
public $actsAs = array('Containable');
public $hasMany = array ('City');
..
}
and:
City.php
class City extends Model {
public $name = 'City';
public $actsAs = array('Containable');
public $belongsTo = array('User');
..
}
In my controller I use :
$user = $this->User->find('all');
but it doesn't work. In sql dump, cakephp uses a find only on tbl users.
Why? Where I wrong?
I normally place recursive to -1 and containable in app model, so it applies to all models you create unless you override specifically.
class AppModel extends Model {
public $actsAs = array('Containable');
public $recursive = -1;
}
Your relationships are fine, although I usually add className and foreignKey just to be safe and clear. In your controller you should do something like this:
$users = $this->User->find('all', array(
'contain' => array(
'City'
)
));
Recursive will prevent any associated records being included by default, this is good as sometimes you do not need the recursive data and extra data will help slow down your application.
Next adding contain into your find call may seem like a chore but it will be clear and concise what you are querying, any 3rd party developer will understand exactly what you are doing if they know how to use Cake. Hope this helps.