Unity OnWillCreateAsset ask for DeveloperName - unity3d

when creating a new script in unity I have a script that changes various pieces of information generating the copyright information attached to the file, however while most information is either static or procedurally determined the name of the active programmer can't be determined in either way, I am trying to show a popup before the asset is actually created asking for the name of the developer but my current method provides only an error, is there a way around this?
using UnityEngine;
using UnityEditor;
/* Project Name : Project Venom
* Script Name : ScriptKeywordProcessor
* Script Path : /Editor/ScriptKeywordProcessor.cs
* Script Author : FaalFaazDov || Raistlin M. Thoreson
* Created On : 08/29/2016 12:46
* Modified On : 09/28/2016 18:25
* Version : 1.1.0
*/
/*************************************************************************
*
* Biophase Entertainment
* __________________
*
* [2016] Biophase Entertainment
* All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains
* the property of Biophase Entertainment and its suppliers,
* if any. The intellectual and technical concepts contained
* herein are proprietary to Biophase Entertainment
* and its suppliers and may be covered by Canadian and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information, reproduction of this material or attempting
* to read the content of these files is strictly forbidden unless prior written
* permission is obtained from Biophase Entertainment.
*
*/
internal sealed class ScriptKeywordProcessor : UnityEditor.AssetModificationProcessor {
public string DeveloperName = "";
public static void OnWillCreateAsset(string path) {
EditorWindow window = EditorWindow.CreateInstance<ScriptKeywordProcessor> ();
window.Show ();
}
void OnGUI() {
GUILayout.Label ("Developer Name", EditorStyles.boldLabel);
DeveloperName = GUILayout.TextField (DeveloperName, 100);
}
}
the error I am recieving is
Assets/Editor/ScriptKeywordProcessor.cs(39,38): error CS0309: The type
ScriptKeywordProcessor must be convertible to
UnityEngine.ScriptableObject in order to use it as parameter T in
the generic type or method
UnityEngine.ScriptableObject.CreateInstance<T>()

From your code, the ScriptKeywordProcessor is not an EditorWindow which is inherited from ScriptableObject.
You need to define another class inherited from EditorWindow to do GUI works. Then open your window in the OnWillCreateAsset method of ScriptKeywordProcessor.

Related

Replace the rendering engine of a composition Moodle 4.1?

I tried to follow Moodle’s documentation on how to replace a rendering engine, but it doesn’t work for some reason.
I have created a theme following the documentation steps and Then I created a renderers.php file at the root of my project. I added the following lines of code in the renderers.php file:
class theme_overridetest_core_calendar_renderer extends core_calendar_renderer {
/**
* Disabled creation of the button to add a new event (Was: Creates a button to add a new event)
*
* #param int $courseid
* #param int $day
* #param int $month
* #param int $year
* #return string
*/
protected function add_event_button($courseid, $day=null, $month=null, $year=null) {
return '';
}
}
After reviewing the documentation I read a passage that dissatisfied that this way of proceeding was for the older versions of Moodle, I would like to know the one used for version 4.1

TYPO3 Extension: How to make a relation to another extension’s model optional?

I have an events extension (for TYPO3 9 LTS and 10 LTS), say MyVendor\MyEvents and a Locations extension, say MyVendor\MyLocations.
The Model MyVendor\MyEvents\Domain\Model\Events has a property eventLocation which is defined to be an object of MyVendor\MyLocations\Domain\Model\Locations.
Now I want to make the relation to MyVendor\MyLocations\Domain\Model\Locations optional. I have found a way for the TCA to show a different form field in the backend depending on the MyLocations extension being installed. But I have no idea how to make all the type definitions in the Events model conditional. They are crucial for the extension to work:
namespace MyVendor\MyEvents\Domain\Model
class Events extends \TYPO3\CMS\Extbase\DomainObject\AbstractEntity
{
/**
* #var \MyVendor\MyLocations\Domain\Model\Locations
*/
protected $eventLocation = NULL;
/**
* #return \MyVendor\MyLocations\Domain\Model\Locations $eventLocation
*/
public function getEventLocation()
{
return $this->eventLocation;
}
/**
* #param \MyVendor\MyLocations\Domain\Model\Locations $eventLocation
* #return void
*/
public function setEventLocation(\MyVendor\MyLocations\Domain\Model\Locations $eventLocation)
{
$this->eventLocation = $eventLocation;
}
}
In case MyVendor\MyLocations is loaded it needs to be defined as above, in case it isn’t loaded it should be just an integer.
In the TCA I am using if (TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('my_locations')) for showing a different field in the backend form for an event.
The Locations Model is in a separate extension because I am using it in a third extension as well.
In your events extension you could setup a repository for locations. Then you can map this repository to your location extensions model via TypoScript.

In an extbase extension, how to access the persistence layer from a scheduler task?

What sounds a bit academic in the title is actually quite straightforward: I have set up a TYPO3 6.1 extbase extension that I've equipped with a scheduler task. The task is supposed to import a CSV file and save it into the extension's database fields.
But how do I tell the scheduler task to use the extension's model etc. and save the received data into the persistence layer?
I've seen this answer to a similar question: Execute repository functions in scheduler task and I think it points the right way, but I think need a full example to start understanding how the dependency injection works.
First you have to consider the aspect of performance:
If you want to insert a big amount of data, you should not use the Extbase persistence for such a task. Because if you do so, it will generate an object for each row you want to insert and persist it immediately. This is quite slow and has a big memory footprint.
If you don't have much data or you split the jobs (e.g. perform 100 import jobs per scheduler run), then use the Extbase persistence.
You can have both in CommandController context, and since CommandControllers are straight-forward to set up, you should go for them instead of an own Scheduler task.
Using Extbase persistence
In the CommandController, inject your repository:
/**
* myRepository
*
* #var \Venor\Myext\Domain\Repository\MyRepository
* #inject
*/
protected $myRepository
Then iterate through the rows you want to import (foreach) and create a new object for every row and add it to your repository:
$myObject = $this->objectManager->get('Vendor\Myext\Domain\Model\MyModel');
$myObject->setProperty('foo');
$myObject->setOtherProperty('bar');
$this->myRepository->add($myObject);
To actually save the objects to the database, you need to persist them. So you also inject the persistenceManager:
/**
* #var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
* #inject
*/
protected $persistenceManager;
And use it:
$this->persistenceManager->persistAll();
You should not do that for every single object (for performance reasons); but for memory usage reasons you should not wait until after thousands of objects to persist, either. So you just insert an iterator to your foreach loop and persist every 20th, 40th, or whatever loop.
Please don't forget that the Scheduler works in Backend context, so the TypoScript must be available by module.tx_yourext. If you want to share the same settings/storagePid with the frontend part of your app, use
module.tx_yourext.persistence < plugin.tx_yourext.persistence
[...]
The TypoScript needs to be present in the root page of your website for backend modules/CommandControllers to use them. I suggest you add the stuff to myext/Configuration/TypoScript/setup.txt and add the static template of your extension to the root page.
Using DataHandler
The TYPO3 DataHandler (formerly TCEmain) is the engine the TYPO3 backend uses for inserting and modifying database records. It is very powerful.
Instead of an object, inside your loop you create an array containing all the data. The first array index is the table, the next level is the affected record, where NEW means that a new record is created. Then you can just set every field of a table with the desired value
$data = array();
$data['be_users']['NEW'] = array(
'pid' => 0,
'username' => $staffMember['IDPerson'],
'password' => md5(GeneralUtility::generateRandomBytes(40)), // random password
'usergroup' => '1,2',
'email' => $staffMember['Email'],
'realName' => $staffMember['Nachname'] . ' ' . $staffMember['Vorname'],
'lang' => 'de',
);
Now you can make an Instance of DataHandler and persist the changes:
/** #var $tce t3lib_TCEmain */
$tce = GeneralUtility::makeInstance('TYPO3\CMS\Core\DataHandling\DataHandler');
$tce->bypassAccessCheckForRecords = TRUE;
$tce->start($data, array());
$tce->admin = TRUE;
$tce->process_datamap();
$newRecordsUidArray = $tce->substNEWwithIDs['NEW'];
Please note the line $tce->admin = TRUE. This suggests to DataHandler that an admin is performing the action. This is convenient because you don't have to set allowed exclude fields for the Scheduler user and can also insert records to PID 0. But it is a possible security flaw, so carefully consider its usage.
Records inserted/updated by DataHandler logged correctly, can be reverted etc.. You can find some examples (such as adding pictures, resolving MM relations) here. In this case all DataHandler related functions were moved to an external repository class that is injected to the CommandController as described above (it's just named in Extbase convention).
A good overview of DataHandler functions can be found here.
In Addition to lorenz's answer: Beginner's Guide to set up a Command Controller Scheduler task:
My example is an import task. Change the Name part "Import" to your needs.
Create a new file EXT:Classes/Controller/ImportCommandController.php
<?php
namespace NAMESPACE\Myextension\Controller;
/***************************************************************
* Copyright notice
*
* (c) 2014
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
/**
*
*
* #package Myextension
* #license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
*
*/
class ImportCommandController extends \TYPO3\CMS\Extbase\Mvc\Controller\CommandController {
/**
* itemRepository
*
* #var \NAMESPACE\Myextension\Domain\Repository\ItemRepository
* #inject
*/
protected $itemRepository;
/**
* #var \TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager
* #inject
*/
protected $persistenceManager;
/**
*
* #param \integer $storagePid
* #param \string $url
*
* #return bool
*/
// very nice: parameters will be fields in the scheduler!
public function importCommand($storagePid = 0,$url = NULL) {
$source = utf8_encode(utf8_encode(file_get_contents($url)));
// set storage page ourselves
// not sure if really necessary
$querySettings = $this->itemRepository->createQuery()->getQuerySettings();
$querySettings->setRespectStoragePage(FALSE);
$this->itemRepository->setDefaultQuerySettings($querySettings);
// do your stuff here
$source = 'foo';
$rendered = 'bar';
// then store it
// this seems to be only necessary if we don't have an existing item yet
// but as we don't know that here, we have to do it
$item = $this->objectManager->get('STUBR\Therapiestellen\Domain\Model\Item');
// find all existing items
$all = $this->itemRepository->findAll();
// if we have an item already, take the first (and only one)
if(count($all) > 0){
$item = $all->getFirst();
}
// set / update properties
$item->setSource($source);
$item->setRendered($r);
$item->setPid($storagePid);
// either update or add it
if(count($all) > 0){
$this->itemRepository->update($item);
}
else {
$this->itemRepository->add($item);
}
// persist it
$this->persistenceManager->persistAll();
}
}
?>
In EXT:ext_localconf.php, add the command controller:
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['extbase']['commandControllers'][] = 'NAMESPACE\\Myextension\\Controller\\ImportCommandController';
Configure in Scheduler:
That's basically it!

How can I protect my methods bodies (not the attached JavaDoc and Signature) using Acceleo code-generator

I use Acceleo in order to generate code with a model I have made. I managed to protect my methods in order to protect them usinig "#generated NOT" in case I need to regenerate my code with Acceleo. The problem is that adding #generated NOT protect all the method content, that is to say the body, the signature and JavaDocs.
The thing is that I only need to keep the method body, or at least the method body and its signature, but I need the doc to be updated. How can I do this ?
Just for information here is an example of a potential generated class :
/*
* #generated
*/
public class ActeurRefEntrepriseServicesImpl implements ActeurRefEntrepriseServices {
#Autowired
HelloWorldService helloWorldService;
/**
* Service which say hello
*
* #param name
* user name
* #return print Hello username
*
* #generated NOT
*/
#Override
public void sayHello(final String name) {
helloWorldService.print(name);
}
}
Baptiste,
The #generated tags use the standard EMF protection rules : "#generated" means that the body of the block for which it is set will be generated, anything else means no re-generation. If you set something as "#generated" in any of your metamodels' generated code, you will see that there, too, the javadoc is preserved whatever the edits you do.
In short, you cannot tell EMF to re-generate anything other than the code itself.
If you need to have the body protected but not the javadoc, you have to shift from the "#generated" protection to Acceleo's [protected] blocks. i.e, change your template from :
[template generatedMethod(methodName : String)]
/**
* Some doc.
* #param param1
* param documentation.
* #generated
*/
[generateSignature(methodName)/] {
[generateBody()/]
}
[/template]
to something using a protected block :
[template generatedMethod(methodName : String)]
/**
* Some doc.
* #param param1
* param documentation.
*/
[protected (methodName)]
[generateSignature(methodName)/] {
[generateBody()/]
}
[/protected]
[/template]
With this paradigm, anything that is outside of the protected area will be regenerated, everything else will remain untouched by a regeneration.
See also the full documentation available from the Acceleo website.
If you absolutely need to use the "#generated" protection method for your model, you will need to tamper with the JMerger API from EMF and alter the launcher Acceleo generated for you in order to use your own merging strategy (see the getGenerationStrategy method from that launcher). Note that this is by no means an easy task.

Sudzc for Magento web services

I am in very bad situation, I got the objectiveC classes from the sudzc website.
using "http://www.xxx.in/mstore/api/soap/?wsdl"
in "SDZMagentoServiceExample.m" class I get one method
[service call:self action:#selector(callHandler:) sessionId: #"" resourcePath: #"catalog_category.level" args: (id)args];
It always gives me parameter error like
"Invalid website code requested:" if I pass dictionary or array in the args.
Please help me, I am in very bad situation.
thanks in advance.
From
/**
* Catalog category api
*
* #category Mage
* #package Mage_Catalog
* #author Magento Core Team <core#magentocommerce.com>
*/
class Mage_Catalog_Model_Category_Api extends Mage_Catalog_Model_Api_Resource
{
Following code:
/**
* Retrieve level of categories for category/store view/website
*
* #param string|int|null $website
* #param string|int|null $store
* #param int|null $categoryId
* #return array
*/
public function level($website = null, $store = null, $categoryId = null)
{
So nor array, nor dictionary would be accepted. Only raw string or int value.
I will not be able to help you in Objective C code, but I can show you some light with PHP. You can try out this type of call:-
$proxy = new SoapClient('http://www.iphone5case.in/mstore/api/soap/?wsdl');
$sessionId = $proxy->login('apiUser', 'apiKey');
/**
* As defined in the "Manage Stores" section of Admin panel,
* where you need to use the specific Website Code and/or Store Code
*/
$websiteCode = null;
$storeCode = 'german';
// Parent Category ID
$parentCategoryId = 2;
$firstLevel = $proxy->call($sessionId, 'category.level', array($websiteCode, $storeCode, $parentCategoryId));
Now if you print this variable "$firstLevel", you will get your required output, from this Web Service API.
Also whenever you are using Magento SOAP API v1, then each of the arguments will need to be as an array element. In this case, following are the main parameters expected for this API call "category.level":-
Website Code or ID
Store View Code or ID
Parent Category ID
So you need to create an array, and put sequentially each of the above arguments as array elements, like:-
array(
$websiteCode,
$storeCode,
$parentCategoryId
)
Lastly, please make sure that you reference this article always, as you can get the usage of almost all the Web Service API methods here.
Hope it helps.