Deleting an Attribute Category when uninstalling package

Permalink 1 user found helpful
I'm creating a package that installs a new AttributeKeyCategory:
$pkg = parent::install();
AttributeKeyCategory::add('widget', true, $pkg);


That all works great, but if I try to uninstall and re-install, I get an error message that the search index attributes table already exists:
mysql error: [1050: Table 'widgetsearchindexattributes' already exists] in EXECUTE("CREATE TABLE WidgetSearchIndexAttributes ( widgetID INTEGER(11) UNSIGNED NOT NULL DEFAULT 0, PRIMARY KEY (widgetID) )")

The installation bombs at this error.

I've been trying to follow the core code for uninstalling a package and, from what I can tell, the category is removed from the AttributeKeyCategories table, but I can't seem to find where the 'WidgetSearchIndexAttributes' table would get removed, if at all.

If I uninstall the package, manually remove the 'WidgetSearchIndexAttributes' table and reinstall the package, it all works okay.

Should I just run this SQL on installation of the package?
DROP TABLE IF EXISTS WidgetSearchIndexAttributes

SkyBlueSofa
 
Job replied on at Permalink Reply
Job
Look at the following, this is the function that is run when you delete a Attribute Category through the dashboard:

public function delete_set() {
      if ($this->token->validate('delete_set')) { 
         $as = AttributeSet::getByID($this->post('asID'));
         if (!is_object($as)) {
            $this->error->add(t('Invalid attribute set.'));
         } else if ($as->isAttributeSetLocked()) { 
            $this->error->add(t('This attribute set is locked. That means it was added by a package and cannot be manually removed.'));
            $this->edit($as->getAttributeSetID());
         }
         if (!$this->error->has()) {
            $categoryID = $as->getAttributeSetKeyCategoryID();
            $as->delete();
            $this->redirect('dashboard/system/attributes/sets', 'category', $categoryID, 'set_deleted');
         }         
      } else {


(I found this in /concrete/controllers/dashboard/system/attributes/sets.php).

Using this I'd probably go for something like this in your packages uninstall() (i think its that one!) function:

$as = AttributeSet::getByHandle("widget");
   if (!is_object($as)) {
        // error handling
   } else { 
      $as->delete();
   }


Not tested any of this, but I can't see why it wouldn't work.

If this answer solves your problem, don't forget to mark it as Answered :-).

Job.
Job replied on at Permalink Reply
Job
Scrap that - answered a question you didn't ask. Let me look again.
Job replied on at Permalink Reply
Job
OK, try this:

$akc = AttrbiuteKeyCategory::getByHandle("widget);
if(is_object($akc)) {
  $akc->delete();
}


Again, not tested.

Job.
SkyBlueSofa replied on at Permalink Reply
SkyBlueSofa
Job, thanks for the quick response. Here's where I'm at with this:

Running
$akc->delete();
runs this code block:
public function delete() {
   $db = Loader::db();
   $this->clearAttributeKeyCategoryTypes();
   $this->clearAttributeKeyCategoryColumnHeaders();
   $this->rescanSetDisplayOrder();
   $db->Execute('delete from AttributeKeyCategories where akCategoryID = ?', $this->akCategoryID);      
}
and there is a comment in the code directly above this function
/** 
    * note, this does not remove anything but the direct data associated with the category
    */

And therein lies the rub: $akc->delete(); removes everything *except* the actual table. I think perhaps I should manually delete the table either at the start of Package::install or at the end of Package::uninstall.
I just wanted to know if this was the best way to do it or not. I don't want to duplicate code.
JohntheFish replied on at Permalink Best Answer Reply
JohntheFish
eCommerce has a bunch of things that attributes get attached to and deletes some attribute related tables in the package uninstall method. If there was a better way, I guess this would be the place to find it.

public function uninstall() {
  parent::uninstall();
  $db = Loader::db();
  //....
  //....
  $db->Execute('drop table if exists CoreCommerceOrderSearchIndexAttributes');
  $db->Execute('drop table if exists CoreCommerceProductSearchIndexAttributes');
  //....
  //....
}
SkyBlueSofa replied on at Permalink Reply
SkyBlueSofa
As I delved into this issue more, that's what I assumed I'd need to do. Thanks.

I don't think that creating new AttributeKeyCategories is done much, so the code for dealing with them isn't as up to date as other parts of the core. <- My opinon

Perhaps the core team has a reasoning behind it. Team?
Job replied on at Permalink Reply
Job
"I don't think that creating new AttributeKeyCategories is done much"

What are they actually for? I've never evne come across them I don't think ...
SkyBlueSofa replied on at Permalink Reply
SkyBlueSofa
Job,

Categories are essentially buckets that information can go into.

There are 3 Attribute Key Categories that are installed with with the core c5:
* Collection
* User
* File

Generally, as c5 is page-centric, the 3 default categories are enough (or can be modified in order to work for what is needed. The functionality that I'm looking for is:
* Widgets that can exist outside of pages and aren't tied to any one page
* Widgets that can be owned or supported by one or more users
* A Widget may have multiple files

After looking all this, I decided that a new category was in order. Besides, it helps me learn more of the core.