Install custom attributes with a custom block type

Permalink 1 user found helpful
I'm building a custom block and I would like for the block to add a new File Attribute Set with some File Attributes when installed. I can't seem to find anything in the documentation about how to go about doing this, but I do know it is possible as many of the add-ons I've installed from the marketplace add page & user attributes when I've added them to a site.

 
Mainio replied on at Permalink Best Answer Reply
Mainio
Usually you could just check in the code that already does this to see an example.

And one more thing: this should be done in the package's installation process and not in the block's installation process. This way you can automate few things, like when uninstalling your package, it will automatically uninstall all these as well.

But here's how to do it:
// Assuming you've just installed your package
$pkg = parent::install();
// For adding FILE attribute key set + attributes to that set
// 1. First add the set (please note this is not necessary if you don't want the attributes to a set but you mentioned you do want them into a set)
$cat = AttributeKeyCategory::getByHandle('file');
$set = $cat->addSet('your_set_handle', 'Set Name', $pkg);
// 2. Add the actual attribute
$at = AttributeType::getByHandle('text'); // Adjust the attribute type to your needs
$key = FileAttributeKey::add($at, array(
  'akHandle' => 'your_attribute_key_handle',
  'akName' => 'The name of this attribute',
  'akIsSearchable' => 1, // file manager searchable
  'akIsSearchableIndexed' => 1, // included in indexed search
  'akIsEditable' => 0 // I'm not really sure what this does for file attributes
), $pkg);


That is quickly written, untested and just to show how it's done but I hope you'll get on the right track with that. Written with the latest concrete5 API, so I'm not sure whether that works with older versions of c5 (which you should take into account if you'll publish that block into the marketplace).
jlego replied on at Permalink Reply
Don't think I will be publishing the block. Thanks for the code. I will test it out.
jlego replied on at Permalink Reply
So I tested this out. I had to add the following for the Attribute functions to work properly:
Loader::model('file_attributes');


Something interesting is happening though. The Attributes install but when I visit the File Attributes page in Dashboard the css and jquery appear to stop working. (there is no styling or UI)
Not sure what is going on there. It is only the Files>Attributes page itself, if I click on one of the Attributes or Manage Sets the UI returns.

Also I've been reading the following how-tos on making custom attribute types and I've included models>attributes>type>MyAttributeType in the package however I'm not sure how to include that in the install for the package. (A new attribute type is not created when installing the package with just including those files)

http://www.concrete5.org/documentation/how-tos/developers/custom-at...
http://www.concrete5.org/documentation/how-tos/developers/create-a-...
Mainio replied on at Permalink Reply
Mainio
You can add new attribute type like this:

AttributeType::add('my_attribute_type', 'My attribute type', $pkg); // $pkg is the package for which you install this


And there you probably also need Loader::model('attribute/type'). I can test the code above later today to see what's wrong there but one thing I can say is that you should have the attribute type installed before the above works, otherwise it will not work.
jlego replied on at Permalink Reply
From reading this article I've gotten a couple of other snippets
http://www.concrete5.org/community/forums/customizing_c5/installing...

So far this is working (with the exception of disappearing UI on the Files>Attributes page in Dashboard):
$pkg = parent::install();
Loader::model('file_attributes');
Loader::model('attribute/type'); //not sure if this is neccessary? Package installs without it...
//1. First, create a new attribute type
$cakc = AttributeKeyCategory::getByHandle('file'); //only associate this attribute type with files (not pages or users)
$ct = AttributeType::add('custom_type', 'Custom Attribute Type', $pkg); //set the handle and name for the custom attribute
$cakc->associateAttributeKeyType($ct); //associate the attribute
// 2. Second create a new attribute set
$cat = AttributeKeyCategory::getByHandle('file');
$set = $cat->addSet('set_name', 'Custom Set', $pkg);
// 3. Add the actual attributes
$at_text = AttributeType::getByHandle('text'); // a core attribute type
$at_custom = AttributeType::getByHandle('custom_type'); //the custom attribute type created in step 1
$key1 = FileAttributeKey::add($at_text, array(
   'akHandle' => 'at_customText',


Is there any way to set the attribute keys all at once (the last couple of lines)? I tried both of the following methods and get errors on installation:

$set->addKey($key1, $key2);
$set->addKey(array($key1, $key2));
Mainio replied on at Permalink Reply
Mainio
Not that I know of.

Dunno which one is prettier but this is also one option:
foreach (array($ak1,$ak2,$ak3) as $ak) {
  $set->addKey($ak);
}
jlego replied on at Permalink Reply
Would that have any impact on load time using the for each loop vs. setting each one individually? I suppose it doesn't particularly matter since the installation script would only be run once.
Mainio replied on at Permalink Reply
Mainio
Nope, just as many calls. A bit more memory for allocating the array actually but that is not something you should worry about in the installation process.

As long as you can keep the installation process under 5s, everything is basically fine. And what you're trying to do I believe would not even take a second.
jlego replied on at Permalink Reply
Another quick question for you if you don't mind.
I need a select Attribute installed with my own preset values. At first I thought I needed a custom attribute type, but now that I think about it, it would be easier and cleaner to use your approach to create a new attribute of the select type.

Problem is the select attribute type is much more complex than the basic text type. It has 3 database tables with different sets of options. I've tried this:

$at_select = AttributeType::getByHandle('select');
$key_cats = FileAttributeKey::add($at_select, array(
//first table, just like any other attribute type
'akHandle' => 'cs_categories',
'akName' => 'Categories',
'akIsSearchable' => 1, 
'akIsSearchableIndexed' => 1, 
'akIsEditable' => 1, 
//second table. options specific for select type
'akSelectAllowMultipleValues' => 1,
'akSelectAlllowOtherValues' => 0,
'akSelectOptionDisplayOrder' => 1,
), $pkg);

The options from the second table are set on installation, but I'm not completely sure how to set the static values for the select options. The core select type is very complex as it allows adding the options from the UI, so I'm having trouble trying to sort out where it sets those options and how to translate that into the code you provided.
Mainio replied on at Permalink Reply
Mainio
$optobj = SelectAttributeTypeOption::add($key, 'New option');
jlego replied on at Permalink Reply
Thanks!
jgruiz75 replied on at Permalink Reply
I am trying to do something similar. can you post the final code you used to create and populate the select attribute?