| 1 | # Copyright 2001-2007 Six Apart. This code cannot be redistributed without |
|---|
| 2 | # permission from www.sixapart.com. For more information, consult your |
|---|
| 3 | # Movable Type license. |
|---|
| 4 | # |
|---|
| 5 | # $Id$ |
|---|
| 6 | |
|---|
| 7 | package MT::PluginData; |
|---|
| 8 | use strict; |
|---|
| 9 | |
|---|
| 10 | use MT::Serialize; |
|---|
| 11 | |
|---|
| 12 | use MT::Blog; |
|---|
| 13 | use base qw( MT::Object ); |
|---|
| 14 | |
|---|
| 15 | __PACKAGE__->install_properties ({ |
|---|
| 16 | column_defs => { |
|---|
| 17 | 'id' => 'integer not null auto_increment', |
|---|
| 18 | 'plugin' => 'string(50) not null', |
|---|
| 19 | 'key' => 'string(255) not null', |
|---|
| 20 | 'data' => 'blob', |
|---|
| 21 | }, |
|---|
| 22 | indexes => { |
|---|
| 23 | plugin => 1, |
|---|
| 24 | key => 1, |
|---|
| 25 | }, |
|---|
| 26 | child_of => 'MT::Blog', |
|---|
| 27 | datasource => 'plugindata', |
|---|
| 28 | primary_key => 'id', |
|---|
| 29 | }); |
|---|
| 30 | |
|---|
| 31 | sub class_label { |
|---|
| 32 | MT->translate("Plugin Data"); |
|---|
| 33 | } |
|---|
| 34 | |
|---|
| 35 | sub remove { |
|---|
| 36 | my $pd = shift; |
|---|
| 37 | $pd->SUPER::remove(@_) if ref($pd); |
|---|
| 38 | |
|---|
| 39 | # class method call - might have blog_id parameter |
|---|
| 40 | my ($terms, $args) = @_; |
|---|
| 41 | $pd->SUPER::remove(@_) unless $terms && exists($terms->{blog_id}); |
|---|
| 42 | |
|---|
| 43 | my $blog_ids = delete $terms->{blog_id}; |
|---|
| 44 | if ( 'ARRAY' ne ref($blog_ids) ) { |
|---|
| 45 | $blog_ids = [ $blog_ids ]; |
|---|
| 46 | } |
|---|
| 47 | |
|---|
| 48 | my @keys = map { "configuration:blog:$_" } @$blog_ids; |
|---|
| 49 | $terms->{key} = \@keys; |
|---|
| 50 | $pd->SUPER::remove($terms, $args); |
|---|
| 51 | } |
|---|
| 52 | |
|---|
| 53 | { |
|---|
| 54 | my $ser; |
|---|
| 55 | sub data { |
|---|
| 56 | my $self = shift; |
|---|
| 57 | $ser ||= MT::Serialize->new('MT'); # force MT serialization for plugins |
|---|
| 58 | if (@_) { |
|---|
| 59 | my $data = shift; |
|---|
| 60 | if (ref($data)) { |
|---|
| 61 | $self->column('data', $ser->serialize( \$data )); |
|---|
| 62 | } else { |
|---|
| 63 | $self->column('data', $data); |
|---|
| 64 | } |
|---|
| 65 | $data; |
|---|
| 66 | } else { |
|---|
| 67 | my $data = $self->column('data'); |
|---|
| 68 | return undef unless defined $data; |
|---|
| 69 | if (substr($data, 0, 4) eq 'SERG') { |
|---|
| 70 | my $thawed = $ser->unserialize( $data ); |
|---|
| 71 | defined $thawed ? $$thawed : undef; |
|---|
| 72 | } else { |
|---|
| 73 | # signature is not a match, so the data must be stored |
|---|
| 74 | # using Storable... |
|---|
| 75 | require Storable; |
|---|
| 76 | my $thawed = eval { Storable::thaw( $data ) }; |
|---|
| 77 | if ($@ =~ m/byte order/i) { |
|---|
| 78 | $Storable::interwork_56_64bit = 1; |
|---|
| 79 | $thawed = eval { Storable::thaw( $data ) }; |
|---|
| 80 | } |
|---|
| 81 | return undef if $@; |
|---|
| 82 | return $thawed; |
|---|
| 83 | } |
|---|
| 84 | } |
|---|
| 85 | } |
|---|
| 86 | } |
|---|
| 87 | |
|---|
| 88 | 1; |
|---|
| 89 | __END__ |
|---|
| 90 | |
|---|
| 91 | =head1 NAME |
|---|
| 92 | |
|---|
| 93 | MT::PluginData - Arbitrary data storage for Movable Type plugins |
|---|
| 94 | |
|---|
| 95 | =head1 SYNOPSIS |
|---|
| 96 | |
|---|
| 97 | use MT::PluginData; |
|---|
| 98 | my $data = MT::PluginData->new; |
|---|
| 99 | $data->plugin('my-plugin'); |
|---|
| 100 | $data->key('unique-key'); |
|---|
| 101 | $data->data($big_data_structure); |
|---|
| 102 | $data->save or die $data->errstr; |
|---|
| 103 | |
|---|
| 104 | ## ... later ... |
|---|
| 105 | |
|---|
| 106 | my $data = MT::PluginData->load({ plugin => 'my-plugin', |
|---|
| 107 | key => 'unique-key' }); |
|---|
| 108 | my $big_data_structure = $data->data; |
|---|
| 109 | |
|---|
| 110 | =head1 DESCRIPTION |
|---|
| 111 | |
|---|
| 112 | I<MT::PluginData> is a data storage mechanism for Movable Type plugins. It |
|---|
| 113 | uses the same backend datasource as the rest of the Movable Type system: |
|---|
| 114 | Berkeley DB, MySQL, etc. Plugins can use this class to store arbitrary |
|---|
| 115 | data structures in the database, keyed on a string specific to the plugin |
|---|
| 116 | and a key, just like a big associate array. Data structures are serialized |
|---|
| 117 | using I<Storable>. |
|---|
| 118 | |
|---|
| 119 | =head1 USAGE |
|---|
| 120 | |
|---|
| 121 | As a subclass of I<MT::Object>, I<MT::PluginData> inherits all of the |
|---|
| 122 | data-management and -storage methods from that class; thus you should look |
|---|
| 123 | at the I<MT::Object> documentation for details about creating a new object, |
|---|
| 124 | loading an existing object, saving an object, etc. |
|---|
| 125 | |
|---|
| 126 | =head1 DATA ACCESS METHODS |
|---|
| 127 | |
|---|
| 128 | The I<MT::PluginData> object holds the following pieces of data. These fields |
|---|
| 129 | can be accessed and set using the standard data access methods described in |
|---|
| 130 | the I<MT::Object> documentation. |
|---|
| 131 | |
|---|
| 132 | =over 4 |
|---|
| 133 | |
|---|
| 134 | =item * id |
|---|
| 135 | |
|---|
| 136 | The numeric ID of the record. |
|---|
| 137 | |
|---|
| 138 | =item * plugin |
|---|
| 139 | |
|---|
| 140 | A unique name identifying the plugin. |
|---|
| 141 | |
|---|
| 142 | =item * key |
|---|
| 143 | |
|---|
| 144 | A key--like the key in an associative array--that, with the I<plugin> |
|---|
| 145 | column, uniquely identifies this record. |
|---|
| 146 | |
|---|
| 147 | =item * data |
|---|
| 148 | |
|---|
| 149 | The data structure that is being stored. When setting the value for this |
|---|
| 150 | column, the value provided must be a reference. For example, the following |
|---|
| 151 | will die with an error: |
|---|
| 152 | |
|---|
| 153 | $data->data('string'); |
|---|
| 154 | |
|---|
| 155 | You must use |
|---|
| 156 | |
|---|
| 157 | $data->data(\'string'); |
|---|
| 158 | |
|---|
| 159 | instead. |
|---|
| 160 | |
|---|
| 161 | =back |
|---|
| 162 | |
|---|
| 163 | =head1 DATA LOOKUP |
|---|
| 164 | |
|---|
| 165 | In addition to numeric ID lookup, you can look up or sort records by any |
|---|
| 166 | combination of the following fields. See the I<load> documentation in |
|---|
| 167 | I<MT::Object> for more information. |
|---|
| 168 | |
|---|
| 169 | =over 4 |
|---|
| 170 | |
|---|
| 171 | =item * plugin |
|---|
| 172 | |
|---|
| 173 | =item * key |
|---|
| 174 | |
|---|
| 175 | =back |
|---|
| 176 | |
|---|
| 177 | =head1 AUTHOR & COPYRIGHTS |
|---|
| 178 | |
|---|
| 179 | Please see the I<MT> manpage for author, copyright, and license information. |
|---|
| 180 | |
|---|
| 181 | =cut |
|---|