Piotras' blog: Archive
2005-01-01 - 2005-12-31
Foreach...
Posted on 2005-01-12 11:58:35 UTC.
I just noticed that future started last week :)
What I really hate is glib hash tables iterations. While there is ( seems to be nice ) g_hash_table_foreach function , it forces anyone to write additional routine functions which are passed as parameter and sometimes must call another foreach functions. This makes life very difficult.
While we need allocate some memory for GParamSpec which should be used to register midgard classes, we must know how many properties object should have.
GParamSpec *params = g_malloc(sizeof(GParamSpec*)*(number));
Our magic "number" can not be easily get while parsing xml file as it uses _get_elements_names function which is recursive one. g_hash_table_size is very helpfull here , as we can get later hash size , increase by 1 ( to add NULL ) and call sizeof with correct number. Yeah, this is it. But we also need at this point number of property. That's bad.
You may create some easy gint i value which may be used in function which is passed to g_hash_table_foreach. You may , but this value will be set to 0 with every function call. I decided to change midgard MgdHash structure which has gint and GHashTable, so simple hash has also something like index.
typedef struct
{
GHashTable *hash;
gint n;
}
MgdHash;
And this seems to work fine, as indexes are automagically created while xml schema file is parsed. Some more changes seems to be required before commiting code to cvs , especially when I noticed my silly mistake. I added two header files to main src core directory. Anyway header files should be changed a lot , so fresh ones should be added in correct place.
Please, register me :)
Posted on 2005-01-12 17:57:42 UTC.
Finally.
Just called my local midgard-schema tool to check if xml file is correctly defined.
midgard-schema ./MgdObjects.xml
Debug output seems fine till now.
** (process:27960): DEBUG: Registering new 'MgdRpd' typeWhich simply means : I defined MidgardArticle and by default now it extends MgdRpd object. There are some work left to correctly install properties and this is one of these difficult_kill_me_i_do_not_want_do_this things ;)
(process:27960): midgard-schema-DEBUG: Source schema is empty
(process:27960): midgard-schema-DEBUG: TYPE in Schema: MidgardArticle
(process:27960): midgard-schema-DEBUG: Number of properties: 31
** (process:27960): DEBUG: Registering new 'MidgardArticle' type
I also tried to register Piotrasa type, but unfortunatelly I was lazy to write all properties. Luckily mgdlib_create_schema function didn't even try to register such type.
(process:27960): midgard-schema-DEBUG: TYPE in Schema: PiotrasaYeah, debug output is fine , as nobody wants to know how this works ;)
(process:27960): midgard-schema-WARNING **: Type Piotrasa has less than 1 property!
MgdSchema for everyone
Posted on 2005-01-17 16:51:50 UTC.
MgdSchema was born.
g_type_init();
mgdlib_init();
MgdSchema *mschema;
gpointer *bar;
GType topic;
const gchar *name;
name = "MidgardTopic";
topic = g_type_from_name(name);
mschema = mgdlib_create_schema (MGD_SCHEMA_FILE,NULL,NULL);
bar = g_object_new (topic, NULL);
g_object_set (bar,
"title", g_strdup("My lovely title"),
"sitegroup", 12,
"name", g_strdup("name which is easy"),
NULL
);
This short code produces nice debug output:
** (process:19859): DEBUG: Midgard class 'MidgardTopic' initializedAnd interesting thing is , this "object" was created from such xml file:
** (process:19859): DEBUG: Set property title
** (process:19859): DEBUG: Set property sitegroup
** (process:19859): DEBUG: Set property name
<type name="MidgardTopic" table="topic">Interesting? Just notice that sitegroup was not defined in xml :)
<property name="name" type="ext"/>
<property name="title" type="text" table="topic_i"/>
<property name="score" type="integer"/>
</type>
So why such property was set? Because MidgardTopic is not real Midgard object.
It was midgardized :)
Good start before mgd_exorcise() ;)
<? new MidgardRocks(); ?>
Posted on 2005-01-27 17:47:55 UTC.
Yeah, Midgard really rocks.
Define Your own type in schema.
<type name="MidgardRocks">
<property name="name" type="string"/>
<property name="info" type="string"/>
</type>
Open Your favourite midgard's sites editor.
Write short code:
$classname = "MidgardRocks";
if (class_exists($classname)) {
echo "Class $classname exists";
$amerigard = new MidgardRocks();
print_r($amerigard);
}?>
Point Your favourite browser to the page with the code.
Class MidgardRocks exists
MidgardRocks Object ( )
Isn't Midgard Your favourite CMF and CMS? ;)
That was "easy" part. Now there is a high time to define object's properties and methods, which should be a little painfull if you consider using "very well documented" Zend.
I was wondering today why
char class_name[] = "SomeObject";
INIT_CLASS_ENTRY(class, class_name, NULL);
works , while
char *class_name = g_strdup((gchar *)objname);
INIT_CLASS_ENTRY(class, class_name, NULL);
doesn't work.
Solution is "easy". Zend uses sizeof in macro instead of strlen which is much much better to get length of any string, right?
Dynamic registering PHP classess from Midgard schema seems to be a little better , we can remove at least 100 lines of code ( If I am not wrong ) just cause of this:
static void
_register_midgard_php_classes(gpointer key, gpointer value, gpointer user_data){
zend_class_entry class;
class.name = g_strdup((gchar*) key);
class.name_length = strlen((gchar*) key);
class.builtin_functions = NULL;
class.handle_function_call = NULL;
class.handle_property_get = NULL;
class.handle_property_set = NULL;
zend_register_internal_class(&class TSRMLS_CC);
}
Bad thing is that we can not register objects while PHP module is loaded.
We must do it while request is initialized. I wish I could be wrong , and gladly expect any hints for this problem.
A good thing about PHP_RINIT_FUNCTION(midgard) is that we can move mgd_get_midgard code there and forget about calling this function in midgard root file. $_MIDGARD data could be initialized internally and without worry that anyone can change root file.
In other news:
Midgard Apache module (currently Apache2 at this moment) forces using utf-8 parser , so there will be no need to use MidgardParser directive. Of course I am not going to remove this directive , as someone may need to use latin-1 parser.
PHP4 and mysql extension
Posted on 2005-02-04 12:38:29 UTC.
This should do the trick.
Add sources repository to /etc/apt/sources.list file.
( in my case I added Polish mirror )
deb-src ftp://ftp.pl.debian.org/debian testing main contrib non-free
Install mysql client and php4 development packages
apt-get install php4-dev libmysqlclient12-dev
Download php4 sources package.
cd /usr/src apt-get source -d php4 dpkg-source -x php4_4.3.10-2.dsc cd php4-4.3.10/ext/mysql phpize./configure --with-mysql=/usr make cp .libs/mysql.so /usr/lib/php4/20020429/ /etc/init.d/apache stop /etc/init.d/apache start
Point your favourite browser to http://www.cafepress.com/mgd
Find something suitable for You :)
MidgardRocks has name
Posted on 2005-02-04 21:38:17 UTC.
Let me write code's part unformatted as this won't break anything.
Define object.
<type name="MidgardRocks">
<property name="name" type="string"/>
<property name="info" type="string"/>
</type>
Write testing PHP code.
<?php
$amerigard = new MidgardRocks();
print_r($amerigard);
print "<p>";
$amerigard->name = "Midgard is cool";
print_r($amerigard);
?>
Request page.
MidgardRocks Object ( [id] => [sitegroup] => [author] => [owner] => [realm] => [guid] => [changed] => [updated] => [action] => [name] => [info] => )
MidgardRocks Object ( [id] => [sitegroup] => [author] => [owner] => [realm] => [guid] => [changed] => [updated] => [action] => [name] => Midgard is cool [info] => )
You still want to ask about these all undefined properties in xml file?
This is simple. MidgardRocks by default inherits MgdRpd object which has these properties defined.
You do not really need to worry about them.
Code works , but is unstable. I need to find out if there is some other way to define class members.
If not, we need to call class constructor only when object is initialized, so by default all objects called
with new Object will be empty. I am starting to wonder if this is good idea anyway.
Error 404 , /midgard not found.
Posted on 2005-02-10 20:37:53 UTC.
This is a good moment to set Apache log level to debug. Do not try to
find /spider-admin , /midgard or /aegir dir on your filesystem under
DocumentRoot set in Virtual host configuration file. Instead of this ,
open main Apache configuration file and set log level to debug. It is
set by simple directive:
LogLevel debugStop Apache and start again. Request midgard page and take a look at log file.
In many cases you may find debug errors like this one:
[debug] midgard-apache2.c(1314): [client xxx.xxx.xxx.xxx] Midgard: regenerating /var/local/cache/midgard/7-57-12-0.php: cannot open, assuming non-existant
[debug] midgard-apache2.c(2253): [client xxx.xxx.xxx.xxx] Midgard: Couldn't create cache file
It simply means that one of the directory set by MidgardPageCacheDir has not even executable bit.
You should check every dir in this path. The most probably is that the 'cache' directory itself has drwx------ permissions ( the most probably for system when midgard is self compiled and with prefix other than /usr ).
Change permission to drwx--x--x using chmod:
chmod 711 /var/local/cacheNote , that we use only x bit instead of rx as we do not want Apache user to be able to list this directory.
Entry added also in troubleshooting section on www.midgard-project.org
Class , not class.
Posted on 2005-02-13 14:14:16 UTC.
While MidgardRocks class was already initialized and declared with all its members I found this class very unstable and ( frankly speaking ) far from being usefull. I must say *FAR FROM*. Why? Zend extensions idea is good , not great , but good. You can initialize module, define globals , define classes and almost anything You would like to define.
When class is registered it is stored in CG globals HasHTable, so it is available at any time while module is loaded. What about members? You can add class' members by using one of few zend_hash_add_*** internal functions, by adding members ( object's properties ) to zend_class_entry->default_properties.
OK, where is the problem?
When You add members to class while module is initialized, you should mostly use EXACTLY the same functions which are used and defined in zend_compile.c. This simply means that all data and memory allocated should be freed when request shutdown is called. Got the point? You can not add and define class' members once , cause zend needs to destroy these data. This is not wierd when you think about calssess which are defined on PHP level.
Start request, define classess , methods , members and while request is ended , free them all.
Real nightmare from extension point of view.
What makes me "funny" is the fact that class members are destroyed, while class itself is not! It doesn't matter how you define members , and which zend_hash_xxx function will be used.
The most important thing. We need real class constructor. We need object to be initialized with all properties.
We need to extend classes with all parent's properties. I think that we could use some get() method which could be
real class constructor( If Zend knows about such thing as class constructor :/ ) .
What is also interesting. Initialized objects ( think about Zend ) are mostly initialized with 'return_value' internally used by Zend. It looks like no one documented the fact that one may use 'this_ptr' instead of returned value to get
PHP's syntax like $art = new Article();.
What do we need now to make MgdSchema being very usefull with Zend ( The most difficult midgard module to be created IMO )? Looks like we need some kind of "caching" feature to initialize classes only when theses should be used. They can be defined and registered , but empty as long as you will need to use them. And we need to make this during request time. This is bad , but still far more better and faster then define classes on PHP level.
At least we do not waste time which is needed to parse PHP code.
mgd_get_me_by
Posted on 2005-03-02 12:09:37 UTC.
I was wondering about get methods for Midgard (MgdObject) and GObject objects. If we can define get_by_id by defining id property of an object we can simply define any get method following object's properties which are set. This means that after you define object's property up and name you can simply get object exactly as current mgd_get_by_name(up, name). When up and title are set you can call object as mgd_get_by_title(up, title). This method doesn't exists , but do we need to write another method?. This is very simply kind of find() method. The real problem is that you never know if you can get fetchable or single object. get_by_id method always returns object or NULL, which is much more simple from any point of view.
Current methods for MgdObjects, update() or create() work very similiar as simply find() method should work.
We get class' properties, check if property is defined and generate query. PHP ( or Zend ) object's methods works
the same way , we "map" all not MgdObject properties to MgdObject's ones.
So how do I do it using midgard-php extension?
<?phpor
$amerigard = new MidgardRocks();
$amerigard->get_by_id(1);
$amerigard->name = "Midgard is cool";
$amerigard->update();
?>
<?phpEasy?
$amerigard = new MidgardRocks();
$amerigard->name = "Midgard is cool";
$amerigard->create();
?>
Well, it looks easy if you look at this code. update() or create() methods do not take care about ownership, sitegroup or any other access control layer at this moment.
It is almost impossible to define midgard *mgd or MgdSchema per class. The idea of current MgdSchema is that one schema may be shared between applications or virtualhost. So one class' connection or "parent" schema may ( and will ) be different. Current solution is to define object's schema and midgard structure when object is initialized. So new MgdObject is created like this:
MgdObject *obj;
obj = midgard_object_new(midgard *mgd,
MgdSchema *schema,
gchar *name);
Bad thing is that for every object created we need to look for type in schema. But if You consider how fast is midgard core and how slow may be midgard-php application you can agree that one call or querry speed is not important. Important is how fast is getting all data required by application.
SQL querry speed is another issue. We can make one big "join" like querry to get full object when its storage is defined
in more than one table. This is not as fast as one querry to get data from one table. But if you get data from one table
per querry you need to define as many queries as many tables object uses as storage. This means that midgard-php object properties stored in record_extension table can not be retrieved with another API functions. Exactly the same API must be used for replicated or serialized objects. This means that this API should be MgdObject's API. I was also wondering about the same usage for object's attachments. Following parameter's idea you could define blob's mimetype as domain , its name as name and blobs itself as value. Think about "getting" one field from table according to another two ones which may be groupped as array for object's property, assigned as another object or just like parameters.
Another problem with single queries is class inheritance. If MidgardArticle extends MidgardRepligardClass , how querry should be build when all parent class' properties are child's one? If MyMidgard extends MidgardArticle , how should we know which property is from parent class? Search parent class for property?
Lets's look at our update method and its sql querry.
midgard-lib:1065:debug:query=UPDATE article SET up='0',locker='1',
approver='1',revisor='1',creator='1',type=136657063,locked='0000-00-00 00:00:00',
approved='0000-00-00 00:00:00',created='2003-04-28 05:56:46',revision=136656998,
revised='2003-04-30 09:46:00',score=136657126,name='index',extra3='',
extra2='',extra1='',print=136657020,view=136657009,icon=136657073,
caldays=136657114,calstart='1900-00-00',id=1,action='',
updated='',changed='',guid='',realm='' WHERE id=1 AND (sitegroup = 0 OR 0<>0)
midgard-lib:1065:debug:query failed: Unknown column 'action' in 'field list'
Action field is not defined in article table so querry failed. It doesn't matter I did not specify such property with such field in my schema. Property is inherited from parent class. So again. Create two queries and find which class property belongs to? While schema is created it generates parts of sql and store it in MgdSchemaType structure which is assigned to object when this is initialized as its private property. One does not need to waste expensive CPU time to create select querry during get method. The same may be done for create or update methods ( if "may" :).
GParamSpec may be usefull here, as MgdSchema creates "table.field" entries as nick values when define default class members. So MidgardArticle name property has "name" property and "article_i.name" nick. This should also define ACL attributes , as Midgard objects requires more than read and write flags. Property like sitegroup can not be "write" or "read". A special case is required as such property should be updated or created only for SG0 administrator, and with particular ACL API.
When we define flags per property we should be able to control not only object itself , but also every single property.
You can try to use MgdSchema objects with latest CVS tarballs.
Using midgard-php extension you should be able to:
- define class
- initialize object
- get object by id ( $object->get_by_id(int id) )
- create object ( $object->create() )
- update object ( $object->update() )
"Binary guys" responsible for binary packages of Midgard should start using latest CVS soon , as we slowly starting to prepare
1.7alpha release with changed core dependencies and midgard-data supporting fs midcom.
midgard-php ZTS ready
Posted on 2005-03-04 18:48:19 UTC.
No more no less.
While Debian maintainers enabled experimental ZTS feature in all PHP packages which are included in debian distribution , we had no other choice like tune midgard-php extension and make it ready for ZTS.
ZTS is Zend Thread Safety option , but requires php module to use ZTS macros which are absolutely safe while extension is compiled for PHP without ZTS.
Bad thing is that I can not recompile midgard packages for Debian.
We should have new midgard release next week instead. Which is absolutely good thing :)
Get midgard CVS to test ZTS and MgdSchema or wait till morning to get nightly tarballs.
midgard_object_find
Posted on 2005-03-15 15:20:12 UTC.
New midgard-core API function becomes a little usefull.
Library definition:
midgard_res *res;How it works on PHP level?
res = midgard_object_find(MgdObject mobj);
Quite trivial now , simple find() method.
$amerigard = NewMidgardArticle();This method returns fetchables with only id assigned as object property.
$amerigard->topic = $topic_id;
$amerigard->find();
Well, "only id" if you think about typical midgard php objects. There is also well known "N" , "__res__" and new property "errno".
print_r($amerigard);errno set to 0 is MGD_ERR_OK error string. Nothing New. The only difference: object itself handles such property.
NewMidgardArticle Object(
[name] => index
[N] => 6
[__res__] => Resource id #2
[errno] => 0
)
Let's get some more objects.
while ($amerigard->fetch())Hmmm.... It looks like mgd_list_topic_articles() ;)
{
$old_article = mgd_get_article($amerigard->id);
}
and
$amerigard = NewMidgardArticle();looks like mgd_get_article_by_name.
$amerigard->topic = $topic_id;
$amerigard->name = "index";
$amerigard->find();
Current limitation is sitegroup being defined according to host's sitegroup and one table usage. Which means there is no way
to get full object which is multilanged for example. But it is not future limitation :)
Ah! There is another funny "feature" with errno.
$amerigard = NewMidgardArticle();create() method doesn't return id which happens if You use mgd_xxx_create function. Instead of that object changes itself.
$amerigard->topic = $topic_id;
$amerigard->create();
So after calling create method object should have id set to id returned from mysql ( not 0 ) and errno set to 0 ( MGD_ERR_OK ). On failure object->id is set to 0 and errno is set to corresponding error number.
I wonder if this function could return full object and method like find_fast() fetchables ids.
Before April 1st starts
Posted on 2005-03-31 17:14:12 UTC.
I made few important changes in midgard-php extension , and in core header files. ( I still wonder why we have internal.h file , while it is used everywhere and simply all structures from this file could be in midgard.h file, which could make life a bit easier )
Midgard 1.7 release is going to be the first one since 1.4.x when we change dependencies for midgard-core. The most important change is that midgard depends on glib libraries >= 2.6 while we used glib 1.2.
Now, midgard may use ini like files to configure database, host , blobdir and all data which are still configured with Apache directives.
[Database]It is enough to call
#Database host ( 'localhost' by default )
Host=
# Name of the database
Name=
# Username for user who is able to connect to database
Username=
# Password for username
Password=
# etc etc
mgd_config_init("filename"); to initialize midgard in command line php. File passed as parameter to this function is searched in "/etc" directory which depends on prefix defined for midgard-core.In my case , directory config is /etc/midgard/conf.d ( --prefix=/usr ). There is no special convention to name files in conf directory. When you call mgd_config_init("amerigard") you want to initialize midgard from /etc/midgard/conf.d/amerigard file.
Unfortunatelly , all files ( especially with passwords ) stored under /etc directory should be readable only for root. And any user is not able to initialize midgard from command line. Now it means:
- initialize midgard only for installation purposes
- run as root and do not blame anyone when something wrong happens
A good point is that we could use the same configuration file for Apache vhost ( let's say MidgardConfig directive ), command line php , datagard, repligard, and more. If this is going to be a good way of midgard configuration , we should add another one ( only one ) config file where all default global variables are stored, like blobdir , or schemafile. At least, there is no need to specify blobdir , schema or even parser if one wants to follow defaults.
If I write about midgard-php I must write about two new methods ( for every object )
$object ->is_in_tree(int rootid, int id);Checks if object with id id is in object's tree with id rootid.
By default used for objects of the same type.
$object->is_in_parent_tree(int rootid, int id);Checks if object with id id is in parent object's tree with id rootid.
'Parent' doesn't mean parent object whcih is extended. It means parent in tree ( like article->topic ).
You can define parent and some tree data in schema.
<type name="NewMidgardArticle" table="article"There is no need to define which table is used by parent. It is defined in parent's iself definition.
parentfield="topic" parent="NewMidgardTopic'">
You can also wonder why we need two parameters for this function when we could use only one , root's one.
This is often ( I think ) when you check if object is in tree before you get it. In our case we just need to initialize
empty object , only to let midgard-core knows what table should be used.
And in other news
Adam Conrad ( php debian packages maintainer ) disabled ZTS in debian packages.It means that I need to rebuild midgard packages for debian and sing a song "catch me if you can" ;)
Walking the path is knowing the path
Posted on 2005-04-02 22:40:25 UTC.
I just forgot to mention about this last time , when I wrote about tree management. All Midgard objects has invisible and not active 'path' property now.
What does it mean?
When object is created or updated , midgard library "walks" the object's tree and build it's path. So , when we only initialize automagic database and storage creation , the path property could be added to object's table, and anyone could use already defined and set path to get object by path without any need to build it's path during ( very valuable sometimes ) request time. Articles created with MidCom may be get "outside" the MidCom and used with MidCom which makes midgard-php and MidCom much closer and almost the same midgard "extension".
Simple script
Posted on 2005-04-13 11:58:04 UTC.
OK, Midgard has new release. 1.7alpha1.
I wonder what can I do with new code and with new objects and methods ;)
First , I am lazy right now to use my favourite browser , so I will use simple plain PHP file and write some simple code.
<?php
mgd_config_init("amerigard");
/*
* I do initialize midgard internals from 'amerigard' file , which is located
* in /etc/midgard/conf.d/amerigard file in my case
*/
mgd_auth_midgard("admin", "password");
/*
* Note that I did not use third parameter.
* Do I need cookie? In plain text?
* Midgard does not send cookie anymore.
*/
$host = new NewMidgardHost();
/*
* Notice 'New' in class name.
* New midgard types can not overwrite old ones.
*/
$host->name = "localhost";
$host->find();
/* I want to get only host objects which has localhost as name */
while ($host && $host->fetch())
{
print "Host 'localhost' with id $host->id\n";
$oldhost = mgd_get_host($host->id);
$style = new NewMidgardStyle();
$style->get_by_id($oldhost->style);
/*
* Every old object may used as new object
* and every new object may used as old one.
*/
print "This host uses $style->name style \n\n";
}
?>
And the output:
Host 'localhost' with id 1
This host uses Aegir_Master_Style style
Host 'localhost' with id 2
This host uses Empty style
Consider the fact that I run this php script as root. I may use it to setup Midgard database or even manage this database and even virtual hosts without any need to request web pages.
And some style features.
Change virtual host configuration and force midgard apache module to act like old module without caching facilities.
Let's say we have three (different ones) styles with "navi" style element, and we want get one of them during request time.
We need to use mgd_preparse function as Apache module serve page and style elements with this function.
<?php
$current_style = $page->style;
$style_a = 1;
$style_b = 2;
$style_element = "navi";
/*
* Current requested page uses style with id=3.
*/
eval('?>'.mgd_preparse(mgd_template($style_element).'<?php '));
mgd_set_style($style_a);
eval('?>'.mgd_preparse(mgd_template($style_element).'<?php '));
mgd_set_style($style_b);
eval('?>'.mgd_preparse(mgd_template($style_element).'<?php '));
/* Set style to initial value */Every mgd_set_style call forces midgard to "reload" internal style elements storage and gets all style elemements which has style field set to style id used as function parameter. This is not flexible as it should be right now , as this may be used only with "old" midgard apache module. Anyway we are closer now to ability to set midgard internals from other levels.
mgd_set_style($current_style);
/* Do more */
?>
mgd_set_lang
Posted on 2005-04-22 19:20:45 UTC.
Reading this blog's title you may expect some lang features. Yeah, MgdSchema supports multilang.
Part of MgdSchema.xml file which describes page element.
<!-- Multilang features -->As you see "multilang" is set only once, and not for every property. The point is that GObject's MgdSchema data collects all "external" tables which should be used for object building functions, and when MgdSchema gets "multilang" xml element's property , sets table's internal pointer to 1 and make it "multilanged". So simply there is no need to point every property to use multilang. You may of course add another table to object which doesn't use multilang if you really want to use more than two tables for object. Not multilanged tables support is not quite stable yet , as I started to write it on the airport, waiting for the flight to Helsinki to join MgdSchema workshop team. ( BTW , if I am to describe workshop in only one word , I would like to use word Excellent! )
<property name="value" type="text" table="pageelement_i" multilang="yes"/>
<property name="sid" type="integer" table="pageelement_i"/>
<property name="lang" type="integer" table="pageelement_i"/>
Multilang is currently usefull for object retrieval and breaks with mysql errors , when create or update method was called. Let's hope to see this fixed next week. Good news about creating objects is that we follow name rules from current midgard version.
When You do create object you can not create object with the same name and with the same parentfield. Except when name of the object is empty. It doesn't affect objects like MidgardParameter or MidgardAttachemnt. Why?
Because we define such behaviour in schema file.
<type name="NewMidgardEventmember" table="eventmember" parent="NewMidgardEvent"Set eid property ( or eid field in table ) as parent's one.
parentfield="eid">
<type name="NewMidgardParameter" table="record_extension" parentfield="">Set parent's to none which means , duplicate names and do not build tree or path for object.
<type name="NewMidgardSnippet" table="snippet" parent="NewMidgardSnippetdir">Parent is not set at all so by default we set "up" field ( or property ) as parent.
Simple and clear. ( I think so :)
Class members
Posted on 2005-04-28 12:54:14 UTC.
I am sure that every Midgard developer asked himself about this "little" feature. Why all PHP objects which extend Midgard objects have no properties by default?
I was more than happy when I created PHP classess from MgdSchema classess with default members. But I was not happy when I noticed that after first request PHP produces only segfaults.
And here "dancing with per***" begins.
You can register PHP class while module is loaded and make this class persistant for every request. You do not have register it again when RINIT module function is called.
Fine. The real weird thing is that classess registered when module was loaded are persistent and not freed when requests end, but class members are not persistant and freed when every request ends. So after first request you have default_properties hash table empty and null to be freed. With every anoter request you have segfaults and segfaults and almost everything from PHP internals set as object's properties.
At last I found solution ( or maybe only workaround ). When RSHUTDOWN module function is called we do this little trick:
static void _unregister_midgard_php_class_members(gpointer key,
gpointer value, gpointer user_data){
zend_class_entry *mclass;
gchar *class_name = (gchar *) key;
class_name = g_ascii_strdown(class_name, strlen(class_name));mclass->refcount is increased , so Zend won't be destroying this hash table, and thus we can detroy it and keep module working nice and correctly.
if (zend_hash_find(CG(class_table), class_name,
strlen(class_name)+1, (void **) &mclass)==SUCCESS) {
*mclass->refcount = 2;
/* Keep refcount 2, destroy_zend_class function
decrease refcount before calling zend_hash_destroy. */
zend_hash_destroy(&mclass->default_properties);
}
}
Zapisz to tak jak lubisz
Posted on 2005-04-30 15:42:19 UTC.
Zastanawiałem się przez chwilę jak mogę napisać ten krótki tekst.
Dlaczego po Polsku? Wszystko dzięki magicznej funkcji mgd_set_lang().
Funkcja mgd_set_lang użyta z wersją CVS dla Midgard Framework pozwala na tworzenie dowolnej ilości wielojęzykowych obiektów i klass opartych na magicznej ( wiem , nie jestem skromy :) funkcjonalności "technologii" która na co dzień nazywana jest MgdSchema. A to oznacza , że można utworzyc 300 i więcej klas i tyle samo obiektów, które swą treść ( jeśli chcemy tworzyć publikacje oparte na tych obiektach ) mogą prezentować w stu językach w zupełnej separacji od logiki programu
i niezależnie od metadanych obiektu. Konkluzja jest prosta : dziecinnie proste :)
Briefly in English:
Any MgdSchema object may be multilanged with schema definition:
<property "content" multilang="yes" table="some_table">
It doesn't matter which property. It's up to you. MgdSchema will take care about updates and creations.
And of course with function mgd_set_lang() :).
Extend extended
Posted on 2005-05-10 18:11:54 UTC.
Only code:
class Amerigard extends NewMidgardArticle
{
}
class FlyHigh extends Amerigard
{
}
$object = new FlyHigh();
print_r($object);
$object->getByID(17);
output:
flyhigh Object
(
[sitegroup] =>
[author] =>
[owner] =>
[realm] =>
[guid] =>
[changed] =>
[updated] =>
[action] =>
[errno] =>
[errstr] =>
[id] =>
[calstart] =>
[caldays] =>
[icon] =>
[view] =>
[print] =>
[extra1] =>
[extra2] =>
[extra3] =>
[name] =>
[score] =>
[revised] =>
[revision] =>
[created] =>
[approved] =>
[locked] =>
[type] =>
[creator] =>
[revisor] =>
[approver] =>
[locker] =>
[up] =>
[topic] =>
[title] =>
[abstract] =>
[content] =>
[url] =>
[lang] =>
[sid] =>
[contentauthor] =>
)
midgard-lib:5071:debug:query=SELECT sitegroup, realm, guid, action, author
FROM repligard WHERE (realm='article' and id=17) AND (repligard.sitegroup in (0,0))
midgard-lib:5071:debug:query=SELECT up,locked,revision,extra3,view,extra2,print,topic,
name,extra1,approver,revised,creator,type,icon,calstart,approved,caldays,locker,score,
revisor,created,id FROM article WHERE article.id=17 AND (article.sitegroup in (0, 0)
OR 0<>0)
Follow this link , if you really do not understand this code.
Query Builder in action
Posted on 2005-05-19 16:10:58 UTC.
Thanks to Jukka's efforts, we have already working MidgardQueryBuilder.
Let's start with simple example.
/* Define which MgdSchema type should be used and returned by QB */MySQL query executed:
$qb = new midgardquerybuilder("NewMidgardArticle");
/* Define constraints */
$qb->addConstraint("topic", "<", 2);
$qb->addConstraint("title", "=", "News");
/* Execute SQL query and return array*/
$f = $qb->execute();
SELECT article.id FROM article_i,article
WHERE
article.topic < 2 AND article_i.title = 'News'
AND article.id=article_i.sid
As you notice, title property is defined in article_i table while topic property is defined in article table.
Query Builder follows class' tables definition and is able to search for objects which has more than one table as storage.
$qb->execute(); returned array with only one object ( due to record returned by SELECT ), so
print_r($f[0]);
etc etc etc
NewMidgardArticle Object
(
[sitegroup] => 0
[author] => 0
[owner] => 0
[realm] => article
[guid] => cedda8cb461c9f846c73f043aaf888e9
[changed] =>
[updated] =>
[action] => create
[errno] => 0
[errstr] =>
[id] => 28
[calstart] => 0000-00-00
Let's try to use datetime fields:
$qb = new midgardquerybuilder("NewMidgardArticle");
$qb->addConstraint("revised", ">", "2003-04-30 09:46:00");
$f = $qb->execute();MySQL query executed:SELECT article.id FROM article_i,article
WHERE
article.revised > '2003-04-30 09:46:00'
AND article.id=article_i.sid
Now $qb->execute() returned array with 5 objects. I do not want to print'em all , so let's look at revised properties
if were selected correctly:
print_r($f);
Array(
[0] => NewMidgardArticle Object
(
[revised] => 2003-04-30 10:30:06
[1] => NewMidgardArticle Object
(
[revised] => 2003-04-30 10:01:18
[2] => NewMidgardArticle Object
(
[revised] => 2003-04-30 11:03:31
[3] => NewMidgardArticle Object
(
[revised] => 2005-04-05 16:29:16
[4] => NewMidgardArticle Object
(
[revised] => 2005-05-12 12:36:18
Simple , fast and usefull :)
OK, now try to read about classes which extend MgdSchema classes and think how this could be used with Query Builder. PHP classes names are not case-sensitive, and MgdSchema type's names are. So if we could use only lowercases for type and classes names in MgdSchema we could extend MgdSchema classes and use own classes and objects with Query Builder too.
Just like this:
class Amerigard extends NewMidgardArticle
{
}
class FlyHigh extends Amerigard
{
}
$qb = new midgardquerybuilder("FlyHigh");
$qb->addConstraint("topic", "<", 2);
$qb->addConstraint("title", "=", "News");
$f = $qb->execute();MySQL query executed:SELECT article.id FROM
article_i,article
WHERE
article.topic < 2
AND article_i.title = 'News'
AND article.id=article_i.sid
Above example is not working example of course , but could be :)
BloGTK in action
Posted on 2005-07-12 16:02:55 UTC.
The worst blog application? BloGTK. Why? Because it is impossible to run this program if you make any mistake in account configuration. Well, if one may say about account configuration ;) All data are always saved to 'Default' account while pressing "save" for other accounts delete anything you wrote ;)
New MgdSchema methods
Posted on 2005-07-12 17:34:02 UTC.
June was fast , very fast month. My family had a short vacation and midgard developers released beta1 and rc1 release during this month.
The funny thing with 1.7 releases is that only few people pay attention at new file system based midcom , while plenty of users and developers focus on new experimental Midgard2 preview technology :)
I have been thinking about simple and fast list method , which could list "child" objects in tree. It was quite fast to implement midgard_object_list function and $object->list() method for midgard-php. Ah! Too fast. Someone could try to set order using such method. So, what could be the best choice? Midgard Query Builder :)
There are already two similiar methods for new midgard-php objects registered with MgdSchema.
- list() List all objects of the same type which have upfield set to current object's primary field.
- list_childs() List all objects of "child" type which have parentfield defined.
Both method returns new MidgardQueryBuilder object instance with parent or up property already being added ( transparently in core ) as constraint to Midgard Query Builder. Here's some simple example from the code I used for tetsing:$sn = new NewMidgardSnippetdir();
$sn->get_by_id(186);
$qb = $sn->list();
$objects = $qb->execute();
$parent = $objects[0]->get_parent();
Example looks a bit difficult and seems to be too much complicated for such trivial thing which was always made using mgd_list_xxxx functions. Yes, it is , but it is quite good ( perfect ? ;) way to write additional wrappers and make any API which let's you limit objects retrieved from database.
get_parent method returns "parent" ( in tree ) object which is defined with parent and parenfield attributes in midgard schema.
I also added ( interesting IMO ) get method. This is simple method which returns only one object and searches for the object comparing property values directly. Few months ago I wrote about find() method which could be used as a replacement for mgd_get_xxx_by_name, but get is even better.
$article = new NewMidgardArticle();
$article->topic = 1;
$article->name = "index";
$article->get();
No fetchables , no arrays in a place when you expect only one object.
What is also interesting is get_by_path method , which "returns" object if found.
$article = new NewMidgardArticle();
$article->get_by_path(""/192-168-0-17-pptest-root-topic/test/img_0016");
I didn't make many tests , but this method should work without any problems for trees like this: /topic/topic/article/article/article.
I wanted to make get_by_path method asap , cause tarjei is writing new midgard webdav class. Using desktop apps with midgard will be much more than cool pleasure :)
$object->parent
Posted on 2005-07-13 17:02:20 UTC.
I even didn't know that using gnome application with midgard can be so easy and flexible :)
This time I try drivel , it's looks much better than BloGTK , thank you Smallone!.
Following tariej's suggestion I wrote simple parent method today.
What it really does? Just returns class name of object's parent type. Pay attention. Not parent class name which was extended but parent class name which is parent in midgard's tree.
Here's brief definition from schema:
type name="NewMidgardArticle" parent="NewMidgardTopic"
$article = new NewMidgardArticle();
$parent = $article->parent()
print $parent;
NewMidgardTopic
Something you should know about metadata.
Posted on 2005-07-20 16:07:27 UTC.
Metadata definition for a good start.
It's good ( and even very good ) that new MgdSchema objects have new methods and midgard-php have new functions which describe classes' and objects' data ( like property type ) , and internal classes' data like: "which property keeps data ( id or guid ) which points directly to object's parent object in midgard tree". Writing code without such knowledge is sometimes like writing code with closed eyes.
I was a bit confused when I decided to use exactly the same enum type data in core and in midgard-php. Why? Because making iteration for enum is "easy as hell". At last I found solution in Alexander's repligard code , which let me create simple GSList and use its position as php integer value and its data as name to register constant.
So , new midgard-php constants are already usable.
MGD_META_PROPERTY_PARENT
( use it when you want to know which property ( it's name ) points to parent object in midgard tree )
Schema definition: <property name="topic" type="integer" parentfield="topic"/>
MGD_META_PROPERTY_UP
( use it when you want to know which property ( it's name ) points to up object in midgard tree, usually object of the same type )
Schema definition: <property name="up" type="integer" upfield="up"/>
MGD_META_PROPERTY_PRIMARY
( use it when you want to know which property ( it's name ) is used as primary field ( id or guid ))
Schema definition: <property name="id" type="integer" primaryfield="id"/>
MGD_META_TREE_PARENT
( use it when you want to know the name of parent object's in midgard tree )
Schema definition: <type name="NewMidgardArticle" parent="NewMidgardTopic">
MGD_META_TREE_CHILDS
( use it when you want to know how many child ( in midgard tree ) objects ( and their names ) may be used for object )
There is no schema definition for this. Child types are created automagically when schema is loaded.
OK , let's look at some sample code. These constants may be used as function's or object method's parameters.
mgd_get_class_data( int metatype, string class name);
returns property name or array if found or false on failure
Yes, I am not happy with function which returns string or array , but you always know what you want to get while
writing code.
$parent = mgd_get_class_data(MGD_META_PROPERTY_PARENT , "NewMidgardArticle");
/* or, if you would like to use object :
$art = new NewMidgardArticle();
$parent = $art->get_data(MGD_META_PROPERTY_PARENT);
*/
print $parent;
output:
topic
Another example:
$topic = new NewMidgardTopic();output :
$childs = $topic->get_data (MGD_META_TREE_CHILDS);
print_r($childs);
Array
(
[NewMidgardArticle] =>
[NewMidgardArt] =>
[PPNewMidgardArt] =>
[org_openpsa_document] =>
)
OK. What about properties metadata?
mgd_get_class_var(string property name, string class name);
returns array with property name as key
$name = mgd_get_class_var("name", "NewMidgardTopic");
/* or
$topic = new NewMidgardTopic();
$name = $topic->get_var("name");
*/
print_r($name);output:
Array
(
[name] => Array
(
[type] => string
)
)
mgd_get_class_property is an alias to mgd_get_class_var.
mgd_get_class_vars(string class name);
returns array with all class default properties and their types
$props = mgd_get_class_vars("NewMidgardTopic");output:[...]etc etc etc
[revision] => Array
(
[type] => int
)
[created] => Array
(
[type] => string
)
[revisor] => Array
(
[type] => int
)
mgd_get_class_properties function is an alias to mgd_get_class_vars.
is element loaded?
Posted on 2005-07-20 18:13:27 UTC.
Quite relaxing to write mgd_is_element_loaded function after metadata initial implementation was done ;)
bool mgd_is_element_loaded(string element name);
returns true if element is already loaded , false if not
This function doesn't care if you think about style or page element.
Example?
$a = mgd_is_element_loaded("code-init");
var_dump($a);
$b = mgd_is_element_loaded("amerigard");
var_dump($b);
output:
bool(true)
bool(false)
Midgard Query Builder multilanged more
Posted on 2005-07-30 15:20:23 UTC.
It was very frustrating experience to try to make mgd_list_xxx functions really easily working with multilanged objects. Well, it appears that such functions can not be used with ML'ed objects in real life as what you can get ( and fetch ) are objects with some lang set and additionally "the same" objects dulicated with lang 0.
I used to use ML Midgard feature only with mgd_get_xxx functions , so midgard ML'ed fetchables became something weird.
Luckily I was able to "fix" this missed feature with Midgard Query Builder. So now , using QB all objects returned by execute method have no duplicated ( lang 0 ) ones. Additionaly you are able to limit objects and get only these ones which use particular language.Follow midgard documentation to see how set_lang method works.
Additionally QB has count method which returns number of objects returned by query.
In theory this "should be" '$qb->count()' times faster than count($qb->execute).
Read docs and blame me
Posted on 2005-08-01 19:00:25 UTC.
Never blame Midgard :)
MgdSchema API for midgard-php objects is updated.
I also updated mRFC 12.
Just send me mail or join #midgard if you would like to see docs more detailed.
Forget about midgard-php5
Posted on 2005-08-04 18:28:22 UTC.
Do not forget about midgard-php4. Module name may suggest only PHP4 support but we have php5 support since today. midgard-php5 and midgard-php4 modules have been merged to one midgard-php4 module and all the trick you have to do is to call correct php-config and correct phpize while trying to build midgard-php4 against PHP5.
Debian users who want to compile against PHP5 should do:
phpize5
./configure --with-apxs=/usr/bin/apxs \
--with-apr-config=/usr/bin/apr-config \
--with-php-config=/usr/bin/php-config5
make
make install
zend.com is your best friend
Posted on 2005-08-14 02:21:12 UTC.
Do I really need to spend so much time on reading zend sources?
Do I need to write 1500 lines of code to find 15 working while making PHP extension using Zend?
I think I do not.
Zend and its products could make me happy.
Zend.com ( not linked, this is the last website you want to
visit , trust me ) is a cure for everything.
Let's look at few sections.
Zend Books
- "Programmers that are relatively new to PHP will find tremendous value in learning the industry standard best practices for PHP development. Experienced PHP programmers will find the guide to [...]"
- "PHP 5 Power Programming"
- "PHP and MySQL Web Development"
- "Advanced PHP Programming"
My mistake, not this link. They talk about PHP , not Zend. I had to be blind.
ZendStudio
- "The Proven PHP Development Environment"
- "complete development solution for PHP"
- "database applications with PHP"
- "Zend Studio 4 Standard is designed for both PHP novices and advanced programmers."
My mistake, not this link. They talk about PHP , not Zend. I had to be blind.
"Zend Engine- The Heart of PHP"
They talk about Zend engine. ... hmmm that's all.
I expected something more than "zend engine".
My mistake, not this link. They talk about PHP , not Zend. I had to be blind.
More links with "Zend" title describe PHP.
Zend "Knowledge Base" returns "No matching results found" for zend API functions.
So what should I do? THE Contest!
Select the best match:
- a) they are extremely stupid
- b) they are very extremely stupid
- c) they are very very extremely stupid
- d) muzgi mają, no normalnie muzgi mają
Table and columns OK
Posted on 2005-08-18 01:59:35 UTC.
Good to know, first midgard database was modified automagically with midgard-schema command line tool which reads Midgard Schema XML file and use GObjects to modify database.
I had no this pleasure to create tables and columns ( but I will soon :) and I was able to modify database defined in new Midgard config file.
Usage is quite simple and trivial now.
`midgard-schema filename`
Filename is name of the file which exists in main midgard
config directory.
/etc/midgard/conf.d in my case ( we always follow prefix
defined for midgard-core ).
I used new OpenPSA2 schema and new MidCOM schema (global
Midgard schema is used automagically) and it took "only" 35
seconds to modify database. It could be faster anyway , but I
couldn't find any good way to create column if they not exist
already in database. So what midgard_object_create_storage
function does is:
1) Try to alter table and add column
2) if add fails try to modify it
( all in all types may change and database must be updated )
What about some usefull debug argument used with
midgard-schema? There is no need to have it. Debug level is
defined in configuration file. So database modification output
( with Loglevel set to message ) looks like this:
midgard-core(m): Table and columns for 'NewMidgardSnippet' OK
midgard-core(m): Column password for password property not created
Something's bad with password property ( message is not clever
at this point , but believe me I modify table and write this
blog, and this is initial midgard-schema usability ).
Let's switch Loglevel to debug ( default is warning , so such messages won't be printed except errors and warnings ).
Schema(d): Type NewMidgardPerson
midgard-core(d): query=CREATE TABLE IF NOT EXISTS person(id int(11) NOT NULL auto_increment, PRIMARY KEY(id))
midgard-core(d): query=ALTER TABLE person ADD password varchar(255)
midgard-core(d): query failed: Duplicate column name 'password'
midgard-core(d): query=ALTER TABLE person MODIFY password varchar(255)
midgard-core(d): query failed: Specified key was too long. Max key length is 500
I wonder about this error. PRIMARY KEY and indexes wasn't
touched.
BTW, log messages ( which can be logged to file ) starts with log domain name.So here this is very clear that we use external application which uses midgard-core."Schema" is a domain name defined for midgard-schema application.
Now think about midgard-apache and midgard-php combined log file and you will get very clear picture of Midgard :)
With possibility to add own messages to log file, even from PHP script you will source of your problem faster and easier. Just watching step by step what is going on :)
1.7.1 release delayed
Posted on 2005-08-24 19:17:02 UTC.
Yesterday I sent mail to dev@midgard-project.org list about delayed release. The main reasons why I did it:
We have not fully confirmed memory leaks in latest stable release, and we couldn't confirm attachments bug. Luckily the second one is fixed now and seems like the first one should be too.
Quoting myself:
"The problem with memory leaks in midgard-php4 may be casued by default_properties hash initialized per every class per request and not fully freed at request end. Currently we do not fully follow Zend API to add class members and such members are directly added to zend_class_entry' default_properties hash.
Good news is that I managed to write wrapper which creates zend_entry_functions structure on the fly. It means that we do not have to set class members , but instead we create real object constructor. All objects initialized have properties set and classes which extend base midgard classes have also default members ( properties ) without any need to write own constructor.
And it means that we can register *all* midgard types found in all schemas when module is initialized. Only once when module is loaded and save valuable time when request is initialized. The only one problem here is that all classes are available for every host. To make it "safe" we can use
objects methods only and only when class exists in request schema. In any other case every method should return at least "Access denied"."
Now , good news is : new classes registration procedures are finished , seems to be very stable and what is more important we have the same support for PHP5.
I didn't manage ( yet ) to write additional macros which should refuse any method call for objects not defined in schema. But now I think it is not mandatory for 1.7 branch as we do not support any high level applications with new Midgard technologies.
So, we just wait for developers who test latest branch and we can release quite new release :)
New daily snapshots for cvs branch
Posted on 2005-08-26 15:57:11 UTC.
No doubt. It had to be done.
http://www.midgard-project.org/nightly/branch/
Quite new daily snapshosts builded for latest Midgard CVS branch. Just download ready to use tarballs instead of updating sources from CVS branch.
Dbcreate=yes
Posted on 2005-08-31 16:23:28 UTC.
Quite new configuration option for new Midgard configuration files.
Command line tool midgard-schema is now more "clever" if such option is set to "yes". MgdSchema itself is also "clever" as new attribute "dbtype" is now recognized. Such attribute is used only when columns in table are created or modified. Typical MgdSchema types just ignore this attribute, or better , do not use it. Thanks to Torben for such proposal.
I created today new database ( this can not be done with midgard-core yet ) and used midgard-schema to create tables and columns. dbtype attribute was indeed needed and perfectly helped to modify columns.
Host type's table ( for example ) looks bad with default values used in schema.
describe host info;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| info | varchar(255) | | | | |
+-------+--------------+------+-----+---------+-------+
We should have another type. Absolutely no varchar. What is to be done is to edit schema file and add correct dbtype if default type is not correct.
<type name="midgard_host" table="host">Run midgard-schema again ( empty db without records should be created or modified in less then 10 seconds ).
[...]
<property name="info" type="string" dbtype="set('auth')"/>
describe host info;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| info | set('auth') | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
This database has also new openpsa2 and new midcom tables created.
describe midcom_group_virtual;PRIMARY KEY is created , and guid and sitegroup columns too. All is done automagically :)
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | | PRI | NULL | auto_increment |
| component | varchar(200) | YES | | NULL | |
| identifier | varchar(200) | YES | | NULL | |
| name | varchar(255) | | | | |
| guid | varchar(80) | | MUL | | |
| sitegroup | int(11) | | MUL | 0 | |
+------------+--------------+------+-----+---------+----------------+
New operators for MidgardQueryBuilder
Posted on 2005-09-03 15:40:22 UTC.
IN, NOT LIKE
I added these new operators to MidgardQueryBuilder constraints.IN operator should be very usefull for functions or object methods which could replace old midgard xxx_in_tree functions.
Simple note and example is now available in Midgard wiki documentation.
What is very interesting I also found and resolved quite important QueryBuilder's bug. When SQL operator used with constraints was invalid, QB selected all records from object's table.
Additionally PHP's phpinfo function reports now MgdSchema technology used.
MgdSchema metadata , the very first view
Posted on 2005-09-24 13:35:10 UTC.
This is the very first view so do not expect fully usable MgdSchema objects' metadata :)
MgdSchema metadata require the biggest and very difficult database change if you look back for midgard database updates in a past. However we have now quite usable midgard-data with datagard tool , so such update is done by dg.
What properties you can find as metadata ones? Currently not much. Author, created date, approved date, etc etc.
Example from real php object is better :
midgard_article Object
(
[guid] => 4f47cf4279a0bdc500c03edc459d4654
[sitegroup] => 0
[metadata] => midgard_metadata Object
(
[creator] =>
[created] => 2003-01-16 14:22:19
[revisor] => f6b665f1984503790ed91f39b11b5392
[revised] => 2003-04-30 10:30:06
[revision] => 3
[locker] => f6b665f1984503790ed91f39b11b5392
[locked] => 0000-00-00 00:00:00
[approver] => f6b665f1984503790ed91f39b11b5392
[approved] => 0000-00-00 00:00:00
[author] => f6b665f1984503790ed91f39b11b5392
[owner] =>
)
You may notice guid property being set. All MgdSchema types use this property automagically now without any need to select it from repligard table. Well, I have some work to do anyway. I "only" need to set those metadata properties when object is created or updated ;)
mgd_check_quota
Posted on 2005-11-16 15:27:26 UTC.
Warm up, new Midgard release is already planned.
Stable Midgard branch now includes improved quota support. MgdSchema technology used with quota made this feature faster and more precise.
How to start:
Follow old Midgard API function to create quota limits.
<?php
$sg = 1;
$tablename = "wholesg";
$spacefields = ""; /* define which content fields should be limited */
$number = 0; /* we set no limits for sitegroup's records , so set different number if you want to limit sg records usage */
$space = 50000; /* ( value as KB ) we set 50MB quota limit */
/* be logged in as SG0 admin */
mgd_create_quota (sitegroup, tablename, spacefields, number, space);
?>
Initialize limits check.
You may define quota check per vhost using midgard-apache directive.
MidgardCheckQuota On
or using midgard-php API function
<?php mgd_check_quota(); ?>
This function may be used everywhere in a code. In code-global, code-init or even in page or style element. Using this function you may check quota limits only in particular requests.
What happens next?
Nothing unusual ;).
Midgard returns MGD_ERR_QUOTA ( "Quota reached" ) error when you want to create new midgard object ( legacy or MgdSchema one ) and quota limit is reached.
Any time you may check quota usage ( whole sitegroup ) using new API function.
<?
/* You must be logged in as SG0 admin */
$size = mgd_get_sitegroup_size(int $sg);
print $size; /* Notice that value is returned in bytes */
?>
Midgard attachments
Posted on 2005-11-23 13:04:32 UTC.
I have just read Arttu's blog about attachments and images.
And I must say I am always a bit confused when I see how attachments can and could be served.
There is well known way of serving images from MidCOM or Aegir.
- /attachment/[sitegroup GUID]/[attachment GUID]/attachment_name.ext to
- /midcom-serveattachmentguid-[attachment GUID]/attachment_name.ext
Every time I see that kind of way to serve attachments I ask myself : "how it is easy and fast to serve attachments like this for pages and styles?".
The answer is simple, not easy and not fast.
Consider few facts:
1. Style assigned to page doesn't use plenty of images.
( Well, 20 or 30 images attached to page is not plenty of me. 200 or 300 could be some number in such case )
2. Midgard Apache module is able to serve images attached to page without any special code or without any need to know image's guid or id.
3. Midgard Apache module doesn't ( when serving image attached to page ):
- initialize,load style and page elements
- initialize midgard preparser
- load midgard-root file
- make additional selects from database to parse page ( and elements ) and serve attachment
1. Upload image ( myfavourite.png ) attaching it to some object. Find its guid. Write code:
/attachment/[sitegroup GUID]/[attachment GUID]/myfavourite.png
2. Upload image ( my favourite.png ) attaching it to page and write html code :
/page/myfavourite.png
Second case requires only 1 ( say : one ) select from database.
Isn't it fast and easy?
Join
Posted on 2005-11-23 14:04:49 UTC.
Very hot and fresh method for MidgardQueryBuilder.
$qb->join(string property, string join_classname, string join_property);
- property , property name which is a member of class defined for Query Builder
- join_classname , classname which should be joined
- join_property, property name which is a member of joined classname
$qb = new MidgardQueryBuilder("midgard_article");
$qb->add_constraint("creator", "=", 10);
$qb->join("creator", "midgard_person", "id");
$qb->execute();
And query:
SELECT guid, article.sitegroup, metadata_creator, metadata_created, metadata_revisor, metadata_revised, metadata_revision, metadata_locker, metadata_locked, metadata_approver, metadata_approved, metadata_author, metadata_owner, metadata_schedule_start, metadata_schedule_end, metadata_hidden, metadata_nav_noentry, metadata_size, article.up AS up,locked,revision,extra3,view,extra2,print,article.author AS author,article.topic AS topic,name,extra1,approver,revised,creator,type,icon,calstart,approved,caldays,locker,score,revisor,article.created AS created,article.id AS id,sid,article_i.created AS contentcreated,article_i.author AS contentauthor,url,content,lang,abstract,title FROM article_i,article,person WHERE article.creator = 10 AND article.id=article_i.sid AND article_i.lang IN (0, 0) AND article.creator=person.idInteresting? I think metadata fields are noticable :)
Let's try to use metadata with QB then:
$qb = new MidgardQueryBuilder("midgard_article");
$qb->add_constraint("name", "=", "index");
$qb->add_constraint("metadata.created", ">", 20050101);
$qb->add_order("metadata.created", "DESC");
$qb->execute();And query:SELECT guid, article.sitegroup, metadata_creator, metadata_created, metadata_revisor, metadata_revised, metadata_revision, metadata_locker, metadata_locked, metadata_approver, metadata_approved, metadata_author, metadata_owner, metadata_schedule_start, metadata_schedule_end, metadata_hidden, metadata_nav_noentry, metadata_size, article.up AS up,locked,revision,extra3,view,extra2,print,article.author AS author,article.topic AS topic,name,extra1,approver,revised,creator,type,icon,calstart,approved,caldays,locker,score,revisor,article.created AS created,article.id AS id,sid,article_i.created AS contentcreated,article_i.author AS contentauthor,url,content,lang,abstract,title FROM article_i,article WHERE (article.name = 'index' AND metadata_created > '20050101') AND article.id=article_i.sid AND article_i.lang IN (0, 0) ORDER BY metadata_created DESC
Join method requires some details to be changed in Query Builder, and should be documented soon.
As well as metadata properties.
QB get_guid
Posted on 2005-11-25 13:55:09 UTC.
Just implemented for MidgardQueryBuilder.
$qb->get_guid(void);
Nice method which returns only object's guids as an array ( on PHP level ) instead of full objects. With faster query and faster value "allocator".
$qb = new MidgardQueryBuilder("midgard_article");
$qb->add_constraint("topic", ">", 0);
$qb->add_constraint("name", "=", index);
$qb->get_guid();
And query:
SELECT article.guid FROM article_i,article WHERE (article.topic > 0 AND article.name = 'index') AND article.id=article_i.sid AND article_i.lang IN (0, 0)
Intersting and good thing is that this method if fully metadata, sitegroup and multilang aware. In near future ACL will be added to "aware" list :)