[Yazlist] Modifications on PHP/YAZ "complete"

Joseph R. Gruber jgruber at tampabay.rr.com
Sun Jan 25 14:59:23 CET 2004


Is it possible that we might see this introduced into a future release of
PHP YAZ?  The work we do over at Project Gutenberg/Distributed Proofreaders
would be much easier with this since we currently have pseudo-code that
loops through the records and pulls these fields now (and it ain't perfect!
LOL).

I'd love to see this in a release!!

Joseph Gruber

> -----Original Message-----
> From: yazlist-bounces at indexdata.dk [mailto:yazlist-bounces at indexdata.dk]
> On Behalf Of Adam Dickmeiss
> Sent: Tuesday, January 13, 2004 10:28 AM
> To: Discussion on the YAZ Z39.50 toolkit
> Subject: Re: [Yazlist] Modifications on PHP/YAZ "complete"
> 
> Hi Christoffer,
> 
> and thank you for the patch. Looks good, so far.
> 
> You made three functions, field, cfield, field. Note these names are not
> acceptable to the PHP folkds. These names are just too generic and do
> not specify where they belong (extensionwise). So they'd have to be
> given some sort of prefix..
> 
> The same names are also class functions. And with those, the names are
> not a problem.
> 
> Thank you for the contribution.
> 
> -- Adam
> 
> Christoffer Landtman wrote:
> 
> > Dear all,
> >
> > The previously discussed modifications are now completed, and can be
> > found in the attached patch.
> >
> > The modifications contain 3 new functions, all accessible via and
> > object; when running yaz_record, "object" is the trigger to submit to
> > get access to all these functions. Here are some small examples:
> >
> > ...
> > $obj = yaz_record($id[$i],$p,"object");
> > print_r($obj);
> > $record = $obj->field("020", "a");
> > print_r($record);
> > $cfield = $obj->cfield('001');
> > print_r($cfield);
> > $ffield = $obj->ffield("020", "ISBN: %a is good!");
> > print "RESULT FROM FFIELD: ".$ffield;
> > ...
> >
> > which will result in the following output:
> >
> > ...
> > GRS Class Object
> > (
> >     [handle] => Resource id #3
> > )
> > Array
> > (
> >     [a] => 9515013062
> > )
> > Array
> > (
> >     [@] => 0000000005
> > )
> > RESULT FROM FFIELD: ISBN: 9515013062 is good!
> > ...
> >
> > The functions are as follows:
> >
> > array field(string field, string subfield)
> > array cfield(string controlfield)
> > string ffield(string field, string syntax)
> >
> > field and cfield are just fetching functions that will return arrays
> > with matches, whereas ffield is a bit more advanced and could in an
> > operative sense be compared with printf(), however with the difference
> > that You submit the field-code instead of what type You expect.
> >
> > This is the first "draft" of the modifications, and it is very
> > possible that the new functions may break under special conditions.
> >
> > There is one noticeable limitation in the current setup, which is that
> > the longest formatted string that can be is 1024 characters. This was
> > intended to be dynamic, i.e. growing, but we were not able to figure
> > out a way that did not result in a segmentation fault of some other
> > component of the PHP/YAZ module.
> >
> > A note to the authors of the PHP/YAZ module that hopefully will look
> > at the modifications is that the modifications have been made on a
> > regrettably old version of the module (1.57.2.1), and might as such be
> > a pain to implement in recent versions. We tried to generate a patch
> > against the most recent release, but this, as expected did result in a
> > terrible mess, and as such we sincerely hope that You might have some
> > more powerful tools to compare (e.g. CVS). The attached patch is as
> > such against version 1.57.2.1 of the module, and in case You cannot
> > make any sense of the patch, I will have to manually generate a better
> > patch.
> >
> > Please comment on the modification, and feel free nag on approaches
> > made in the module. I will certainly not feel offended as this is the
> > first PHP-module I have ever done, and neither are my C-coding skills
> > anything to brag with...=)
> >
> > I hope some of You will find these modifications as useful as we have
> > seen them to be in the future versions of Emilda [1]
> >
> > Best regards,
> >
> > --
> > [1] http://emilda.org
> >
> >------------------------------------------------------------------------
> >
> >--- /usr/src/php-4.3.1/ext/yaz/php_yaz.c	2002-11-14
16:06:40.000000000
> +0200
> >+++ php_yaz.c	2004-01-13 13:12:15.000000000 +0200
> >@@ -16,7 +16,7 @@
> >    +--------------------------------------------------------------------
> --+
> >  */
> >
> >-/* $Id: php_yaz.c,v 1.57.2.1 2002/11/14 14:06:40 iliaa Exp $ */
> >+/* $Id: php_yaz.c,v 1.1 2004/01/13 11:12:15 lanttis Exp $ */
> >
> > #ifdef HAVE_CONFIG_H
> > #include "config.h"
> >@@ -52,6 +52,9 @@
> >
> > #define MAX_ASSOC 100
> >
> >+// RN: The static, maximum length of the formatted return value
> >+#define FORMATTED_LEN 1024
> >+
> > typedef struct Yaz_AssociationInfo *Yaz_Association;
> >
> > struct Yaz_AssociationInfo {
> >@@ -107,6 +110,10 @@
> > static Yaz_Association *shared_associations;
> > static int order_associations;
> > static int le_link;
> >+// RN: Declare GRS struct link
> >+static int le_grs_link;
> >+// RN: GRS class defs
> >+static zend_class_entry *grs_class_entry_ptr;
> >
> > static unsigned char third_argument_force_ref[] = {
> > 	3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
> >@@ -140,6 +147,15 @@
> > 	{NULL, NULL, NULL}
> > };
> >
> >+// RN: GRS object functions
> >+function_entry grs_class_functions[] = {
> >+	PHP_FE(field, NULL)
> >+	PHP_FE(cfield, NULL)
> >+	PHP_FE(ffield, NULL)
> >+	{NULL, NULL, NULL}
> >+};
> >+
> >+
> > static void get_assoc (INTERNAL_FUNCTION_PARAMETERS, pval **id,
> >                        Yaz_Association *assocp)
> > {
> >@@ -911,6 +927,97 @@
> > 	}
> > }
> >
> >+// RN: Function to fetch signle field information
> >+static void fetch_field (zval *match_array, Z_GenericRecord *p, char
> *field, char *sfield)
> >+{
> >+	Z_GenericRecord *grs[20];
> >+	int eno[20];
> >+	int level = 0;
> >+
> >+	//MAKE_STD_ZVAL(return_value);
> >+
> >+	if (array_init(match_array) == FAILURE)
> >+	{
> >+		zval *return_value;
> >+		RETURN_FALSE;
> >+	}
> >+	eno[level] = 0;
> >+	grs[level] = p;
> >+	int match = 0;
> >+	int done = 0;
> >+	while (level >= 0 && !match)
> >+	{
> >+		Z_TaggedElement *e = 0;
> >+		Z_GenericRecord *p = grs[level];
> >+		int i;
> >+		char tag[256];
> >+		int field_match = 0;
> >+		int sfield_match = 0;
> >+
> >+		if (eno[level] >= p->num_elements)
> >+		{
> >+			--level;
> >+			if (level >= 0)
> >+				eno[level]++;
> >+			continue;
> >+		}
> >+		// eno[level]++;
> >+
> >+		for (i = 0; i<=level; i++)
> >+		{
> >+			int tag_type = 3;
> >+			e = grs[i]->elements[eno[i]];
> >+
> >+			if(!strcmp(sfield, "*"))
> >+				sfield_match = 1;
> >+
> >+			if (e->tagValue->which == Z_StringOrNumeric_string)
> >+			{
> >+				if(!strcmp(e->tagValue->u.string, field)) {
> >+					field_match = 1;
> >+				}
> >+				else if(!strcmp(e->tagValue->u.string,
sfield)) {
> >+					sfield_match = 1;
> >+				}
> >+			}
> >+			// does this case ever happen?
> >+			else if (e->tagValue->which ==
> Z_StringOrNumeric_numeric)
> >+			{
> >+				php_error(E_ERROR, "Tag was numeric,
handling not
> currently present: %d", *e->tagValue->u.numeric);
> >+			}
> >+		}
> >+
> >+		switch (e->content->which)
> >+		{
> >+		case Z_ElementData_string:
> >+			if(field_match && sfield_match) {
> >+				add_assoc_string(match_array, e->tagValue-
> >u.string, e->content->u.string, 1);
> >+				done = 1;
> >+			}
> >+			break;
> >+		case Z_ElementData_numeric:
> >+			if(field_match && sfield_match) {
> >+				add_assoc_long(match_array,
e->tagValue->u.string,
> *e->content->u.numeric);
> >+				done = 1;
> >+			}
> >+			break;
> >+		case Z_ElementData_trueOrFalse:
> >+			if(field_match && sfield_match) {
> >+				add_assoc_long(match_array,
e->tagValue->u.string,
> *e->content->u.trueOrFalse);
> >+				done = 1;
> >+			}
> >+			break;
> >+		case Z_ElementData_subtree:
> >+			level++;
> >+			grs[level] = e->content->u.subtree;
> >+			eno[level] = -1;
> >+			if(done)
> >+				match = 1;
> >+		}
> >+
> >+		eno[level]++;
> >+	}
> >+}
> >
> > /* {{{ proto string yaz_record(int id, int pos, string type)
> >    Return record information at given result set position */
> >@@ -973,6 +1080,44 @@
> > 					odr_destroy (odr);
> > 				}
> > 			}
> >+			else if (!strcmp (type, "object"))
> >+			{
> >+				Z_External *ext = (Z_External *)
ZOOM_record_get
> (r, "ext", 0);
> >+				oident *ent = oid_getentbyoid(ext-
> >direct_reference);
> >+
> >+				if (ext->which == Z_External_grs1 &&
ent->value ==
> VAL_GRS1)
> >+				{
> >+					retval_grs1 (return_value,
ext->u.grs1);
> >+				}
> >+				else if (ext->which == Z_External_octet)
> >+				{
> >+					char *buf = (char *)
(ext->u.octet_aligned-
> >buf);
> >+					ODR odr = odr_createmem
(ODR_DECODE);
> >+					Z_GenericRecord *rec = 0;
> >+
> >+					switch (ent->value)
> >+					{
> >+					case VAL_SOIF:
> >+					case VAL_HTML:
> >+						break;
> >+					case VAL_TEXT_XML:
> >+					case VAL_APPLICATION_XML:
> >+						/* text2grs1 (&buf, &len,
t->odr_in,
> 0, 0); */
> >+						break;
> >+					default:
> >+						rec = marc_to_grs1 (buf,
odr);
> >+					}
> >+					if (rec) {
> >+						// RN: Register resource and
create
> object
> >+						zval *handle;
> >+						handle =
zend_list_insert(rec,
> le_grs_link);
> >+						object_init_ex(return_value,
> grs_class_entry_ptr);
> >+
add_property_resource(return_value,
> "handle", handle);
> >+						yaz_log(LOG_DEBUG,
"GRS-handle
> created: %p", handle);
> >+					}
> >+					odr_destroy (odr);
> >+				}
> >+			}
> >             else
> > 			{
> >                 int rlen;
> >@@ -989,6 +1134,176 @@
> > }
> > /* }}} */
> >
> >+// RN: return the resource handle of the grs object
> >+static grs_handle(zval *id)
> >+{
> >+	zval **handle;
> >+	int type;
> >+
> >+	if (!id) {
> >+		php_error(E_ERROR, "Function not called within an object!
> %s()", get_active_function_name(TSRMLS_C));
> >+	}
> >+	if (zend_hash_find(Z_OBJPROP_P(id), "handle", sizeof("handle"),
> (void **) &handle) == FAILURE) {
> >+		php_error(E_ERROR, "Underlying object missing, can't find
> 'this' in %s()", get_active_function_name(TSRMLS_C));
> >+	}
> >+
> >+	return zend_list_find(Z_LVAL_PP(handle), &type);
> >+}
> >+
> >+/* {{{ proto int yaz_field(string field, string subfield)
> >+   Field grepping for the GRS object */
> >+PHP_FUNCTION(field)
> >+{
> >+	char *field_str, *sfield_str;
> >+	zval **pval_field, **pval_sfield;
> >+	int type;
> >+
> >+	if (ZEND_NUM_ARGS() != 2)
> >+		WRONG_PARAM_COUNT;
> >+	if (zend_get_parameters_ex(2, &pval_field, &pval_sfield) == FAILURE)
> >+	{
> >+		WRONG_PARAM_COUNT;
> >+	}
> >+
> >+	convert_to_string_ex (pval_field);
> >+	field_str = (*pval_field)->value.str.val;
> >+	convert_to_string_ex (pval_sfield);
> >+	sfield_str = (*pval_sfield)->value.str.val;
> >+
> >+	Z_GenericRecord *grs = 0;
> >+	grs = (Z_GenericRecord *) grs_handle(getThis());
> >+
> >+	if (grs) {
> >+		fetch_field (return_value, grs, field_str, sfield_str);
> >+	}
> >+	else
> >+		php_error(E_ERROR, "Could not link resource with GRS object
in
> %s()", get_active_function_name(TSRMLS_C));
> >+
> >+}
> >+/* }}} */
> >+
> >+/* {{{ proto int cfield(string cfield)
> >+   Retrun the specified control fileld (001-008) */
> >+PHP_FUNCTION(cfield)
> >+{
> >+	char *cfield_str;
> >+	zval **pval_cfield, *id, **handle;
> >+	zval *value = malloc(sizeof(zval));
> >+	int type;
> >+
> >+	if (ZEND_NUM_ARGS() != 1)
> >+		WRONG_PARAM_COUNT;
> >+	if (zend_get_parameters_ex(1, &pval_cfield) == FAILURE)
> >+	{
> >+		WRONG_PARAM_COUNT;
> >+	}
> >+
> >+	convert_to_string_ex (pval_cfield);
> >+	cfield_str = (*pval_cfield)->value.str.val;
> >+
> >+	Z_GenericRecord *grs = 0;
> >+	grs = (Z_GenericRecord *) grs_handle(getThis());
> >+
> >+	if (grs) {
> >+		fetch_field (value, grs, cfield_str, "@");
> >+		*return_value = *value;
> >+		zval_copy_ctor(return_value);
> >+	}
> >+	else
> >+		php_error(E_ERROR, "Could not link resource with GRS object
in
> %s()", get_active_function_name(TSRMLS_C));
> >+
> >+	free(value);
> >+}
> >+/* }}} */
> >+
> >+// RN: format the field accoring to the given syntax
> >+static format_field(char *formatted, zval *matches, char *syntax)
> >+{
> >+	int i=0;
> >+	int form_len;
> >+	char loop_str[2];
> >+	int find_ok = 0;
> >+	zval **replace;
> >+	int type;
> >+
> >+	loop_str[1] = '\0';
> >+
> >+	while(i <= strlen(syntax))
> >+	{
> >+		find_ok = 0;
> >+
> >+		form_len = strlen(formatted);
> >+		loop_str[0] = syntax[i];
> >+
> >+		if(!strcmp(loop_str, "%")) {
> >+			i++;
> >+			loop_str[0] = syntax[i];
> >+			if(strcmp(loop_str, "%")) {
> >+				if (zend_hash_find(Z_ARRVAL_P(matches),
loop_str,
> 2, (void **)&replace) == FAILURE) {
> >+					formatted = strcat(formatted, "");
> >+				} else {
> >+					find_ok = 1;
> >+					convert_to_string_ex(replace);
> >+					//formatted = realloc(formatted,
> sizeof(formatted)+sizeof(Z_STRVAL_PP(replace)));
> >+					formatted = strcat(formatted,
> Z_STRVAL_PP(replace));
> >+				}
> >+			}
> >+			else {
> >+				formatted = strcat(formatted, &syntax[i]);
> >+			}
> >+		}
> >+		else
> >+			formatted = strcat(formatted, &syntax[i]);
> >+
> >+		if(!find_ok)
> >+			formatted[form_len+1] = '\0';
> >+
> >+		i++;
> >+	}
> >+}
> >+/* }}} */
> >+
> >+/* {{{ proto int ffield(string cfield, string syntax)
> >+   Formats given syntax with subfields from given field */
> >+PHP_FUNCTION(ffield)
> >+{
> >+	char *field_str, *syntax_str;
> >+	zval **pval_field, **pval_syntax;
> >+	char formatted[FORMATTED_LEN];
> >+	formatted[0] = '\0';
> >+	zval *matches = malloc(sizeof(zval));
> >+
> >+	//char *formatted = malloc(10*sizeof(char));
> >+	//strcpy(formatted, "");
> >+
> >+	if (ZEND_NUM_ARGS() != 2)
> >+		WRONG_PARAM_COUNT;
> >+	if (zend_get_parameters_ex(2, &pval_field, &pval_syntax) == FAILURE)
> >+	{
> >+		WRONG_PARAM_COUNT;
> >+	}
> >+
> >+	convert_to_string_ex (pval_field);
> >+	field_str = (*pval_field)->value.str.val;
> >+	convert_to_string_ex (pval_syntax);
> >+	syntax_str = (*pval_syntax)->value.str.val;
> >+
> >+	Z_GenericRecord *grs = 0;
> >+	grs = (Z_GenericRecord *) grs_handle(getThis());
> >+    if(!grs)
> >+		php_error(E_ERROR, "Could not link resource with GRS object
in
> %s()", get_active_function_name(TSRMLS_C));
> >+
> >+	fetch_field (matches, grs, field_str, "*");
> >+
> >+	format_field (formatted, matches, syntax_str);
> >+	yaz_log(LOG_DEBUG, "RESULT: %s", formatted);
> >+
> >+	RETURN_STRINGL(formatted, strlen(formatted), 1);
> >+
> >+	//free(formatted);
> >+	free(matches);
> >+}
> >+/* }}} */
> >
> > /* {{{ proto int yaz_syntax(int id, string syntax)
> >    Set record syntax for retrieval */
> >@@ -1451,11 +1766,22 @@
> > }
> >
> > static void yaz_close_link (zend_rsrc_list_entry *rsrc TSRMLS_DC)
> >-{
> >+{
> > 	Yaz_Association *as = (Yaz_Association *) rsrc->ptr;
> > 	yaz_close_session (as TSRMLS_CC);
> > }
> >
> >+// RN: Destroy GRS resource
> >+static void yaz_grs_destroy(zend_rsrc_list_entry *rsrc TSRMLS_DC)
> >+{
> >+	// Is this handled by odr_destroy?
> >+	/*if((Z_GenericRecord *) rsrc->ptr) {
> >+		yaz_log(LOG_DEBUG, "GRS-handle will be terminated: %p",
rsrc-
> >ptr);
> >+		free(rsrc->ptr);
> >+	}*/
> >+	//yaz_log(LOG_DEBUG, "GRS-handle wannabe-terminated: %p", rsrc-
> >ptr);
> >+}
> >+
> > /* {{{ PHP_INI_BEGIN
> >  */
> > PHP_INI_BEGIN()
> >@@ -1475,7 +1801,6 @@
> > #ifdef ZTS
> > 	yaz_mutex = tsrm_mutex_alloc();
> > #endif
> >-    yaz_log_init_file ("/dev/null");
> > 	ZEND_INIT_MODULE_GLOBALS(yaz, php_yaz_init_globals, NULL);
> >
> >     REGISTER_INI_ENTRIES();
> >@@ -1487,6 +1812,16 @@
> >     }
> > 	le_link = zend_register_list_destructors_ex (yaz_close_link, 0,
> >
> 	"YAZ link", module_number);
> >+
> >+	// RN: Create GRS struct link
> >+	le_grs_link = zend_register_list_destructors_ex (yaz_grs_destroy, 0,
> >+
> 	"GRS structure", module_number);
> >+	// RN: Prerequisities for object
> >+	zend_class_entry grs_class_entry;
> >+
> >+	INIT_CLASS_ENTRY(grs_class_entry, "GRS Class", grs_class_functions);
> >+	grs_class_entry_ptr = zend_register_internal_class(&grs_class_entry
> >+
> 		TSRMLS_CC);
> > 	order_associations = 1;
> > 	shared_associations = xmalloc (sizeof(*shared_associations) *
> MAX_ASSOC);
> > 	for (i = 0; i<MAX_ASSOC; i++)
> >
> >
> >------------------------------------------------------------------------
> >
> >--- /usr/src/php-4.3.1/ext/yaz/php_yaz.h	2002-07-12
14:45:04.000000000
> +0300
> >+++ php_yaz.h	2004-01-13 13:12:15.000000000 +0200
> >@@ -16,7 +16,7 @@
> >    +--------------------------------------------------------------------
> --+
> >  */
> >
> >-/* $Id: php_yaz.h,v 1.13 2002/07/12 11:45:04 sniper Exp $ */
> >+/* $Id: php_yaz.h,v 1.1 2004/01/13 11:12:15 lanttis Exp $ */
> >
> > #ifndef PHP_YAZ_H
> > #define PHP_YAZ_H
> >@@ -53,6 +53,11 @@
> > PHP_FUNCTION(yaz_sort);
> > PHP_FUNCTION(yaz_schema);
> >
> >+// RN: new functions
> >+PHP_FUNCTION(field);
> >+PHP_FUNCTION(cfield);
> >+PHP_FUNCTION(ffield);
> >+
> > ZEND_BEGIN_MODULE_GLOBALS(yaz)
> >     int assoc_seq;
> >     int max_links;
> >
> >
> >------------------------------------------------------------------------
> >
> >_______________________________________________
> >Yazlist mailing list
> >Yazlist at indexdata.dk
> >http://www.indexdata.dk/mailman/listinfo/yazlist
> >
> >
> 
> 
> 
> 
> _______________________________________________
> Yazlist mailing list
> Yazlist at indexdata.dk
> http://www.indexdata.dk/mailman/listinfo/yazlist







More information about the Yazlist mailing list