-
Notifications
You must be signed in to change notification settings - Fork 16
/
catalogues.php
1569 lines (1395 loc) · 63.5 KB
/
catalogues.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?php /*
ocPortal
Copyright (c) ocProducts, 2004-2012
See text/EN/licence.txt for full licencing information.
NOTE TO PROGRAMMERS:
Do not edit this file. If you need to make changes, save your changed file to the appropriate *_custom folder
**** If you ignore this advice, then your website upgrades (e.g. for bug fixes) will likely kill your changes ****
*/
/**
* @license http://opensource.org/licenses/cpal_1.0 Common Public Attribution License
* @copyright ocProducts Ltd
* @package catalogues
*/
/**
* Standard code module initialisation function.
*/
function init__catalogues()
{
global $PT_PAIR_CACHE;
$PT_PAIR_CACHE=array();
global $CAT_FIELDS_CACHE;
$CAT_FIELDS_CACHE=array();
// We do not actually necessarily use these constants in the code (they're based on an extensive of an old BINARY field): but they're here for reference so as to understand the codes
if (!defined('C_DT_FIELDMAPS'))
{
define('C_DT_FIELDMAPS',0);
define('C_DT_TITLELIST',1);
define('C_DT_TABULAR',2);
define('C_DT_GRID',3);
}
}
/**
* Get tempcode for a catalogue category 'feature box' for the given row
*
* @param array The database field row of it
* @param ID_TEXT The zone to use
* @param boolean Whether to put it in a box with a title
* @return tempcode A box for it, linking to the full page
*/
function render_catalogue_category_box($row,$zone='_SEARCH',$give_title=true)
{
$content=paragraph(get_translated_tempcode($row['cc_description']),'yghjgfjftgerr');
$url=build_url(array('page'=>'catalogues','type'=>'category','id'=>$row['id']),$zone);
$breadcrumbs=catalogue_category_breadcrumbs($row['id']);
return do_template('SIMPLE_PREVIEW_BOX',array('TITLE'=>$give_title?get_translated_text($row['cc_title']):NULL,'BREADCRUMBS'=>$breadcrumbs,'SUMMARY'=>$content,'URL'=>$url));
}
/**
* Grant all usergroups access to the specified catalogue category.
*
* @param AUTO_LINK The ID of the category that access is being given to
*/
function grant_catalogue_full_access($category_id)
{
$groups=$GLOBALS['FORUM_DRIVER']->get_usergroup_list(false,true);
foreach (array_keys($groups) as $group_id)
{
$GLOBALS['SITE_DB']->query_insert('group_category_access',array('module_the_name'=>'catalogues_category','category_name'=>strval($category_id),'group_id'=>$group_id));
}
}
/**
* Count the entries and subcategories underneath the specified category, recursively.
*
* @param AUTO_LINK The ID of the category for which count details are collected
* @return array The number of entries is returned in $output['num_entries'], and the number of subcategories is returned in $output['num_children'], the (possibly recursive) number of subcategories in $output['num_children_children'], and the (possibly recursive) number of entries is returned in $output['num_entries_children'].
*/
function count_catalogue_category_children($category_id)
{
static $total_categories=NULL;
if (is_null($total_categories)) $total_categories=$GLOBALS['SITE_DB']->query_value('catalogue_categories','COUNT(*)');
$out=array();
$out['num_children']=$GLOBALS['SITE_DB']->query_value('catalogue_categories','COUNT(*)',array('cc_parent_id'=>$category_id));
$out['num_entries']=$GLOBALS['SITE_DB']->query_value('catalogue_entries','COUNT(*)',array('cc_id'=>$category_id,'ce_validated'=>1));
$rec_record=$GLOBALS['SITE_DB']->query_select('catalogue_childcountcache',array('c_num_rec_children','c_num_rec_entries'),array('cc_id'=>$category_id),'',1);
if (!array_key_exists(0,$rec_record)) $rec_record[0]=array('c_num_rec_children'=>0,'c_num_rec_entries'=>0);
$out['num_children_children']=$rec_record[0]['c_num_rec_children'];
$out['num_entries_children']=$rec_record[0]['c_num_rec_entries'];
return $out;
}
/**
* Get an ordered array of all the entries in the specified catalogue.
*
* @param ?AUTO_LINK The ID of the category for which the entries are being collected (NULL: entries are [and must be] passed instead)
* @param ID_TEXT The name of the catalogue
* @param ?array A database row of the catalogue we are working with (NULL: read it in)
* @param ID_TEXT The view type we're doing
* @set PAGE SEARCH CATEGORY
* @param ID_TEXT The template set we are rendering this category using
* @param ?integer The maximum number of entries to show on a single page of this this category (NULL: all)
* @param ?integer The entry number to start at (NULL: all)
* @param ?mixed The entries to show, may be from other categories. Can either be SQL fragment, or array (NULL: use $start and $max)
* @param ?AUTO_LINK The virtual root for display of this category (NULL: default)
* @param ?SHORT_INTEGER The display type to use (NULL: lookup from $catalogue)
* @param boolean Whether to perform sorting
* @param ?array A list of entry rows (NULL: select them normally)
* @param string ocSelect to apply (blank: none).
* @param ?ID_TEXT Orderer (NULL: read from environment)
* @return array An array containing our built up entries (renderable tempcode), our sorting interface, and our entries (entry records from database, with an additional 'map' field), and the max rows
*/
function get_catalogue_category_entry_buildup($category_id,$catalogue_name,$catalogue,$view_type,$tpl_set,$max,$start,$select,$root,$display_type=NULL,$do_sorting=true,$entries=NULL,$_filters='',$_order_by=NULL)
{
if ($_filters!='')
{
require_code('ocselect');
$filters=parse_ocselect($_filters);
} else
{
$filters=mixed();
}
// How to display
if (is_null($display_type))
{
$display_type=get_param_integer('keep_cat_display_type',$catalogue['c_display_type']);
}
// Find catalogue data
$is_ecomm=is_ecommerce_catalogue($catalogue_name);
if (is_null($catalogue))
{
$_catalogues=$GLOBALS['SITE_DB']->query_select('catalogues',array('*'),array('c_name'=>$catalogue_name),'',1);
$catalogue=$_catalogues[0];
}
require_code('fields');
$fields=get_catalogue_fields($catalogue_name);
// Find order field from environment (assuming $_order_by not passed in), and decode to $order_by/$direction which are semantically quite different
if ($do_sorting)
{
global $NON_CANONICAL_PARAMS;
$NON_CANONICAL_PARAMS[]='order';
if (is_null($_order_by))
$_order_by=get_param('order','');
if (($_order_by=='') || (strpos($_order_by,' ')===false/*probably some bot probing URLs -- sorting always has a space between sorter and direction*/))
{
$order_by='0';
$direction='ASC';
foreach ($fields as $i=>$field)
{
if ($field['cf_defines_order']!=0)
{
$order_by=strval($i);
$direction=($field['cf_defines_order']==1)?'ASC':'DESC';
$_order_by=strval($field['id']).' '.$direction;
break;
}
}
} else
{
list($order_by,$direction)=explode(' ',$_order_by);
if (($order_by!='rating') && ($order_by!='add_date') && ($order_by!='distance'))
{
$found=false;
foreach ($fields as $i=>$field)
{
if ($order_by==$field['id'])
{
$order_by=strval($i);
$found=true;
break;
}
}
if (!$found) $order_by='0'; // Could not find
}
}
} else
{
$order_by=mixed();
$direction='ASC';
}
// Get entries in this category
if ($select==='1=1') $select=NULL;
require_code('fields');
if (is_null($entries))
{
list($in_db_sorting,$num_entries,$entries)=get_catalogue_entries($catalogue_name,$category_id,$max,$start,$select,$do_sorting,$filters,$order_by,$direction);
} else // Oh, we already have $entries
{
$num_entries=count($entries);
$in_db_sorting=false;
}
disable_php_memory_limit();
// Work out the actual rendering, but only for those results in our selection scope (for performance)
foreach ($entries as $i=>$entry)
{
if (($in_db_sorting /*Only select rows were grabbed so $i is not the first entry, it is the $start entry*/) || (!$in_db_sorting /*Needs data to do manual sort*/) || (((is_null($start)) || ($i>=$start) && ($i<$start+$max)) && ((!is_array($select)) || ((is_array($select)) && (in_array($entry['id'],$select))))))
{
$entries[$i]['map']=get_catalogue_entry_map($entry,$catalogue,$view_type,$tpl_set,$root,$fields,(($display_type==C_DT_TITLELIST) && (!$is_ecomm) && (!is_null($order_by)))?array(0,intval($order_by)):NULL,false,true,intval($order_by));
}
}
if ($do_sorting)
{
// Render sort change dropdown
$selectors=new ocp_tempcode();
foreach ($fields as $i=>$field)
{
if ($field['cf_searchable']==1)
{
$potential_sorter_name=get_translated_text($field['cf_name']);
foreach (array('ASC'=>'_ASCENDING','DESC'=>'_DESCENDING') as $dir_code=>$dir_lang)
{
$sort_sel=(($order_by==strval($i)) && ($direction==$dir_code));
$_potential_sorter_name=new ocp_tempcode();
$_potential_sorter_name->attach(escape_html($potential_sorter_name));
$_potential_sorter_name->attach(do_lang_tempcode($dir_lang));
$selectors->attach(do_template('PAGINATION_SORTER',array('_GUID'=>'dfdsfdsusd0fsd0dsf','SELECTED'=>$sort_sel,'NAME'=>protect_from_escaping($_potential_sorter_name),'VALUE'=>strval($field['id']).' '.$dir_code)));
}
}
}
foreach (array('add_date'=>'ADDED','rating'=>'RATING') as $extra_sort_code=>$extra_sort_lang)
{
foreach (array('ASC'=>'_ASCENDING','DESC'=>'_DESCENDING') as $dir_code=>$dir_lang)
{
$sort_sel=(($order_by==$extra_sort_code) && ($direction==$dir_code));
$_potential_sorter_name=new ocp_tempcode();
$_potential_sorter_name->attach(do_lang_tempcode($extra_sort_lang));
$_potential_sorter_name->attach(do_lang_tempcode($dir_lang));
$selectors->attach(do_template('PAGINATION_SORTER',array('_GUID'=>'xfdsfdsusd0fsd0dsf','SELECTED'=>$sort_sel,'NAME'=>protect_from_escaping($_potential_sorter_name),'VALUE'=>$extra_sort_code.' '.$dir_code)));
}
}
$sort_url=get_self_url(false,false,array('order'=>NULL),false,true);
$sorting=do_template('PAGINATION_SORT',array('_GUID'=>'9fgjfdklgjdfgkjlfdjgd90','SORT'=>'order','URL'=>$sort_url,'SELECTORS'=>$selectors));
// Sort entries manually
if (!$in_db_sorting) catalogue_entries_manual_sort($fields,$entries,$order_by,$direction);
} else $sorting=new ocp_tempcode();
// Build up entries
$entry_buildup=new ocp_tempcode();
// Possibly some extra stuff for shopping carts
$extra_map=array();
if ($is_ecomm)
{
require_lang('shopping');
$i=0;
for ($i=0;$i<$num_entries;$i++)
{
if (!array_key_exists($i,$entries)) break;
$entry=$entries[$i];
$extra_map[$i]['ADD_TO_CART']=build_url(array('page'=>'shopping','type'=>'add_item','product_id'=>$entry['id'],'hook'=>'catalogue_items'),get_module_zone('shopping'));
}
}
// Now render the correct layout style
switch ($display_type)
{
case C_DT_FIELDMAPS:
for ($i=0;$i<$num_entries;$i++)
{
if (!array_key_exists($i,$entries)) break;
$entry=$entries[$i];
if ((is_null($max)) || ((is_null($start)) || ($in_db_sorting) || ($i>=$start) && ($i<$start+$max)) && ((!is_array($select)) || ((is_array($select)) && (in_array($entry['id'],$select)))))
$entry_buildup->attach(do_template('CATALOGUE_'.$tpl_set.'_FIELDMAP_ENTRY_WRAP',$entry['map']+(array_key_exists($i,$extra_map)?$extra_map[$i]:array()),NULL,false,'CATALOGUE_DEFAULT_FIELDMAP_ENTRY_WRAP'));
}
break;
case C_DT_TITLELIST:
for ($i=0;$i<$num_entries;$i++)
{
if (!array_key_exists($i,$entries)) break;
$entry=$entries[$i];
if (((is_null($start)) || ($in_db_sorting) || ($i>=$start) && ($i<$start+$max)) && ((!is_array($select)) || ((is_array($select)) && (in_array($entry['id'],$select)))))
$entry_buildup->attach(do_template('CATALOGUE_'.$tpl_set.'_TITLELIST_ENTRY',$entry['map']+(array_key_exists($i,$extra_map)?$extra_map[$i]:array()),NULL,false,'CATALOGUE_DEFAULT_TITLELIST_ENTRY'));
}
if (!$entry_buildup->is_empty()) $entry_buildup=do_template('CATALOGUE_'.$tpl_set.'_TITLELIST_WRAP',$entry['map']+array('CATALOGUE'=>$catalogue_name,'CONTENT'=>$entry_buildup),NULL,false,'CATALOGUE_DEFAULT_TITLELIST_WRAP');
break;
case C_DT_TABULAR:
for ($i=0;$i<$num_entries;$i++)
{
if (!array_key_exists($i,$entries)) break;
$entry=$entries[$i];
if (((is_null($start)) || ($in_db_sorting) || ($i>=$start) && ($i<$start+$max)) && ((!is_array($select)) || (is_array($select)) && (in_array($entry['id'],$select))))
{
$tab_entry_map=$entry['map']+(array_key_exists($i,$extra_map)?$extra_map[$i]:array());
if ((get_option('is_on_comments')=='1') && ($entry['allow_comments']>=1) || (get_option('is_on_rating')=='1') && ($entry['allow_rating']==1) || (get_option('is_on_trackbacks')=='1') && ($entry['allow_trackbacks']==1))
{
$url_map=array('page'=>'catalogues','type'=>'entry','id'=>$entry['id'],'root'=>($root==-1)?NULL:$root);
if (get_page_name()=='catalogues') $url_map+=propagate_ocselect();
$tab_entry_map['VIEW_URL']=build_url($url_map,get_module_zone('catalogues'));
} else
{
$tab_entry_map['VIEW_URL']='';
}
$entry_buildup->attach(/*Preserve memory*/static_evaluate_tempcode(do_template('CATALOGUE_'.$tpl_set.'_TABULAR_ENTRY_WRAP',$tab_entry_map,NULL,false,'CATALOGUE_DEFAULT_TABULAR_ENTRY_WRAP')));
}
if ((!is_null($start)) && ($i>=$start+$max)) break;
}
if (!$entry_buildup->is_empty())
{
$head=new ocp_tempcode();
$field_count=0;
foreach ($fields as $i=>$field)
{
if (((($field['cf_put_in_category']==1) && ($view_type=='CATEGORY')) || (($field['cf_put_in_search']==1) && ($view_type=='SEARCH'))) && ($field['cf_visible']==1))
{
if ($field['cf_searchable']==1)
{
$sort_url_asc=get_self_url(false,false,array('order'=>strval($field['id']).' ASC'),true);
$sort_url_desc=get_self_url(false,false,array('order'=>strval($field['id']).' DESC'),true);
$sort_asc_selected=(($order_by==strval($field['id'])) && ($direction=='ASC'));
$sort_desc_selected=(($order_by==strval($field['id'])) && ($direction=='DESC'));
} else
{
$sort_url_asc='';
$sort_url_desc='';
$sort_asc_selected=false;
$sort_desc_selected=false;
}
$head->attach(do_template('CATALOGUE_'.$tpl_set.'_TABULAR_HEADCELL',array('SORT_ASC_SELECTED'=>$sort_asc_selected,'SORT_DESC_SELECTED'=>$sort_desc_selected,'SORT_URL_ASC'=>$sort_url_asc,'SORT_URL_DESC'=>$sort_url_desc,'CATALOGUE'=>$catalogue_name,'FIELDID'=>strval($i),'_FIELDID'=>strval($field['id']),'FIELD'=>get_translated_text($field['cf_name']),'FIELDTYPE'=>$field['cf_type']),NULL,false,'CATALOGUE_DEFAULT_TABULAR_HEADCELL'));
$field_count++;
}
}
$entry_buildup=do_template('CATALOGUE_'.$tpl_set.'_TABULAR_WRAP',array('CATALOGUE'=>$catalogue_name,'HEAD'=>$head,'CONTENT'=>$entry_buildup,'FIELD_COUNT'=>strval($field_count)),NULL,false,'CATALOGUE_DEFAULT_TABULAR_WRAP');
}
break;
case C_DT_GRID:
for ($i=0;$i<$num_entries;$i++)
{
if (!array_key_exists($i,$entries)) break;
$entry=$entries[$i];
if ((is_null($max)) || ((is_null($start)) || ($in_db_sorting) || ($i>=$start) && ($i<$start+$max)) && ((!is_array($select)) || ((is_array($select)) && (in_array($entry['id'],$select)))))
$entry_buildup->attach(do_template('CATALOGUE_'.$tpl_set.'_GRID_ENTRY_WRAP',$entry['map']+(array_key_exists($i,$extra_map)?$extra_map[$i]:array()),NULL,false,'CATALOGUE_DEFAULT_GRID_ENTRY_WRAP'));
}
break;
default:
warn_exit(do_lang_tempcode('INTERNAL_ERROR'));
}
return array($entry_buildup,$sorting,$entries,$num_entries);
}
/**
* Make sure we are doing necessary join to be able to access the given field
*
* @param object Database connection
* @param array Content type info
* @param ?ID_TEXT Name of the catalogue (NULL: unknown; reduces performance)
* @param array List of joins (passed as reference)
* @param array List of selects (passed as reference)
* @param ID_TEXT The field to get
* @param string The field value for this
* @param array Database field data
* @return ?array A triple: Proper database field name to access with, The fields API table type (blank: no special table), The new filter value (NULL: error)
*/
function _catalogues_ocselect($db,$info,$catalogue_name,&$extra_join,&$extra_select,$filter_key,$filter_val,$db_fields)
{
$matches=array();
if (preg_match('#^field\_(\d+)#',$filter_key,$matches)!=0)
{
$ret=_fields_api_ocselect($db,$info,$catalogue_name,$extra_join,$extra_select,$filter_key,$filter_val,$db_fields);
return $ret;
}
// Named
require_code('fields');
$fields=get_catalogue_fields($catalogue_name);
foreach ($fields as $field)
{
if (get_translated_text($field['cf_name'])==$filter_key)
{
$ret=_fields_api_ocselect($db,$info,$catalogue_name,$extra_join,$extra_select,'field_'.strval($field['id']),$filter_val,$db_fields);
return $ret;
}
}
return _default_conv_func($db,$info,$catalogue_name,$extra_join,$extra_select,$filter_key,$filter_val,$db_fields);
}
/**
* Fetch entries from database, with sorting if possible.
*
* @param ID_TEXT Name of the catalogue
* @param ?AUTO_LINK The ID of the category for which the entries are being collected (NULL: entries are [and must be] passed instead)
* @param ?integer The maximum number of entries to show on a single page of this this category (ignored if $select is not NULL) (NULL: all)
* @param ?integer The entry number to start at (ignored if $select is not NULL) (NULL: all)
* @param ?mixed The entries to show, may be from other categories. Can either be SQL fragment, or array (NULL: use $start and $max)
* @param boolean Whether to perform sorting
* @param ?array List of filters to apply (NULL: none). Each filter is a triple: ORd comparison key(s) [separated by pipe symbols], comparison type (one of '<', '>', '<=', '>=', '=', '~=', or '~'), comparison value
* @param ID_TEXT Orderer
* @param ID_TEXT Order direction
* @param string Additional WHERE SQL to add on to query
* @return array A tuple: whether sorting was done, number of entries returned, list of entries
*/
function get_catalogue_entries($catalogue_name,$category_id,$max,$start,$select,$do_sorting,$filters,$order_by,$direction,$extra_where='')
{
$where_clause=is_null($catalogue_name)?'1=1':db_string_equal_to('c_name',$catalogue_name).$extra_where;
if (!is_null($category_id))
{
// WHERE clause
$where_clause.=' AND ';
if (get_option('catalogues_subcat_narrowin')=='1')
{
require_code('ocfiltering');
$where_clause=ocfilter_to_sqlfragment(strval($category_id).'*','id','catalogue_categories','cc_parent_id','cc_id','id');
} else
{
$where_clause='r.cc_id='.strval($category_id);
}
}
if (!has_specific_permission(get_member(),'see_unvalidated')) $where_clause.=' AND r.ce_validated=1';
// Convert the filters to SQL
require_code('ocselect');
list($extra_select,$extra_join,$extra_where)=ocselect_to_sql($GLOBALS['SITE_DB'],$filters,'catalogue_entry',$catalogue_name);
$where_clause.=$extra_where.' AND '.db_string_equal_to('r.c_name',$catalogue_name);
// If we're listing what IDs to look at, work out SQL for this
if ((is_null($category_id)) && (!is_null($select)))
{
if (((is_array($select)) && (count($select)==0)) || ((is_string($select)) && ($select=='')))
{
$entries=array(); // This is saying we are selecting nothing, so just say that - it'll save us a query
} else // Put together some SQL for defining what to select
{
if (!is_array($select))
{
$or_list=$select;
} else
{
$or_list='';
foreach ($select as $s)
{
if ($or_list!='') $or_list.=' OR ';
$or_list.='r.id='.strval($s);
}
}
$where_clause.=' AND ('.$or_list.')';
}
}
require_code('fields');
$fields=get_catalogue_fields($catalogue_name);
$num_entries=mixed();
$cf_type=is_numeric($order_by)?$fields[intval($order_by)]['cf_type']:'';
$can_do_db_sorting=($order_by!='distance') && ($cf_type!='date') && ($cf_type!='just_date') && ($cf_type!='just_time');
if (($do_sorting) && ($can_do_db_sorting))
{
$virtual_order_by=$order_by;
if ($order_by=='add_date')
{
$virtual_order_by='r.ce_add_date';
}
elseif ($order_by=='rating')
{
$bits=_catalogues_ocselect($GLOBALS['SITE_DB'],array(),$catalogue_name,$extra_join,$extra_select,'compound_rating','',array());
if (!is_null($bits)) list($virtual_order_by,)=$bits;
} elseif (is_numeric($order_by)) // Ah, so it's saying the nth field of this catalogue
{
$bits=_catalogues_ocselect($GLOBALS['SITE_DB'],array(),$catalogue_name,$extra_join,$extra_select,'field_'.$order_by,'',array());
if (!is_null($bits))
{
list($new_key,)=$bits;
if (strpos($new_key,'.text_original')!==false)
{
$num_entries=$GLOBALS['SITE_DB']->query_value_null_ok_full('SELECT COUNT(*) FROM '.get_table_prefix().'catalogue_entries r'.implode('',$extra_join).' WHERE '.$where_clause);
if ($num_entries>300) // For large data sets too slow as after two MySQL joins it can't then use index for ordering
{
$virtual_order_by='r.id';
unset($extra_join[$new_key]);
} else
{
$virtual_order_by=$new_key;
}
} else
{
$virtual_order_by=$new_key;
}
} else
{
$virtual_order_by='r.id';
}
}
} else
{
$virtual_order_by='r.id';
}
if (is_null($num_entries))
$num_entries=$GLOBALS['SITE_DB']->query_value_null_ok_full('SELECT COUNT(*) FROM '.get_table_prefix().'catalogue_entries r'.implode('',$extra_join).' WHERE '.$where_clause);
if ($num_entries>300) // Needed to stop huge slow down, so reduce to sorting by ID
{
$in_db_sorting=true;
$virtual_order_by='r.id';
}
$sql='SELECT r.*'.implode('',$extra_select).' FROM '.get_table_prefix().'catalogue_entries r'.implode('',$extra_join).' WHERE '.$where_clause;
$in_db_sorting=$do_sorting && $can_do_db_sorting; // This defines whether $virtual_order_by can actually be used in SQL (if not, we have to sort manually)
if ($in_db_sorting && $do_sorting) $sql.=' ORDER BY '.$virtual_order_by.' '.$direction;
if ($max>0)
{
$entries=$GLOBALS['SITE_DB']->query($sql,$in_db_sorting?$max:NULL,$in_db_sorting?$start:0);
} else
{
$entries=array();
}
return array($in_db_sorting,$num_entries,$entries);
}
/**
* Manually sort some catalogue entries.
*
* @param array Fields array for catalogue
* @param array Entries to sort (by reference)
* @param ID_TEXT What to sort by
* @param ID_TEXT Sort direction
* @return array Entries
*/
function catalogue_entries_manual_sort($fields,&$entries,$order_by,$direction)
{
$num_entries=count($entries);
for ($i=0;$i<$num_entries;$i++) // Bubble sort
{
for ($j=$i+1;$j<$num_entries;$j++)
{
if ($order_by=='distance')
{
$considered_field='DISTANCE_PLAIN'; // Not in there by default, but addons might make it
} else
{
$considered_field='FIELD_'.$order_by;
}
$a=@$entries[$j]['map'][$considered_field];
if (array_key_exists($considered_field.'_PLAIN',@$entries[$j]['map']))
{
$a=@$entries[$j]['map'][$considered_field.'_PLAIN'];
}
$b=@$entries[$i]['map'][$considered_field];
if (array_key_exists($considered_field.'_PLAIN',@$entries[$i]['map']))
{
$b=@$entries[$i]['map'][$considered_field.'_PLAIN'];
}
if (is_object($a)) $a=$a->evaluate();
if (is_object($b)) $b=$b->evaluate();
if ((isset($fields[$order_by])) && ($fields[$order_by]['cf_type']=='date')) // Special case for dates
{
$bits=explode(' ',$a,2);
$date_bits=explode((strpos($bits[0],'-')!==false)?'-':'/',$bits[0],3);
if (!array_key_exists(1,$date_bits)) $date_bits[1]=date('m');
if (!array_key_exists(2,$date_bits)) $date_bits[2]=date('Y');
$time_bits=explode(':',$bits[1],3);
if (!array_key_exists(1,$time_bits)) $time_bits[1]='00';
if (!array_key_exists(2,$time_bits)) $time_bits[2]='00';
$time_a=mktime(intval($time_bits[0]),intval($time_bits[1]),intval($time_bits[2]),intval($date_bits[1]),intval($date_bits[2]),intval($date_bits[0]));
$bits=explode(' ',$b,2);
$date_bits=explode((strpos($bits[0],'-')!==false)?'-':'/',$bits[0],3);
if (!array_key_exists(1,$date_bits)) $date_bits[1]=date('m');
if (!array_key_exists(2,$date_bits)) $date_bits[2]=date('Y');
$time_bits=explode(':',$bits[1],3);
if (!array_key_exists(1,$time_bits)) $time_bits[1]='00';
if (!array_key_exists(2,$time_bits)) $time_bits[2]='00';
$time_b=mktime(intval($time_bits[0]),intval($time_bits[1]),intval($time_bits[2]),intval($date_bits[1]),intval($date_bits[2]),intval($date_bits[0]));
$r=($time_a<$time_b)?-1:(($time_a==$time_b)?0:1);
}
elseif ($order_by=='distance') // By distance
{
$r=(floatval($a)<floatval($b))?-1:1;
} else // Normal case
{
$r=strnatcmp(strtolower($a),strtolower($b));
}
if ((($r<0) && ($direction=='ASC')) || (($r>0) && ($direction=='DESC')))
{
$temp=$entries[$i];
$entries[$i]=$entries[$j];
$entries[$j]=$temp;
}
}
}
return $entries;
}
/**
* Get a map of the fields for the given entry.
*
* @param array A database row of the entry we are working with
* @param ?array A database row of the catalogue we are working with (NULL: read it in here)
* @param ID_TEXT The view type we're doing
* @set PAGE SEARCH CATEGORY
* @param ID_TEXT The template set we are rendering this category using
* @param ?AUTO_LINK The virtual root for display of this category (NULL: none)
* @param ?array The database rows for the fields for this catalogue (NULL: find them)
* @param ?array A list of fields that we are limiting ourselves to (NULL: get ALL fields)
* @param boolean Whether to grab the feedback details
* @param boolean Whether to grab the breadcrumbs details
* @param ?integer Field index to order by (NULL: none)
* @return array A map of information relating to the entry. The map contains 'FIELDS' (tempcode for all accumulated fields), 'FIELD_x' (for each field x applying to the entry), STAFF_DETAILS, COMMENT_DETAILS, RATING_DETAILS, VIEW_URL, BREADCRUMBS
*/
function get_catalogue_entry_map($entry,$catalogue,$view_type,$tpl_set,$root=NULL,$fields=NULL,$only_fields=NULL,$feedback_details=false,$breadcrumbs_details=false,$order_by=NULL)
{
$id=$entry['id'];
$all_visible=true;
require_code('fields');
// Load catalogue if needed
if (is_null($catalogue))
{
$catalogue_rows=$GLOBALS['SITE_DB']->query_select('catalogues',array('*'),array('c_name'=>$entry['c_name']),'',1);
if (!array_key_exists(0,$catalogue_rows)) warn_exit(do_lang_tempcode('MISSING_RESOURCE'));
$catalogue=$catalogue_rows[0];
}
// Update view count
if (get_db_type()!='xml') $entry['ce_views']++;
// Get values
$catalogue_name=$catalogue['c_name'];
$fields=get_catalogue_entry_field_values($catalogue_name,$entry,$only_fields,$fields,false,$view_type);
// Prepare output map
$map=array();
$map['FIELDS']=new ocp_tempcode();
$map['FIELDS_GRID']=new ocp_tempcode();
$map['FIELDS_TABULAR']=new ocp_tempcode();
$map['fields']=$fields;
$fields_1d=array();
$fields_2d=array();
// Loop over all fields
foreach ($fields as $i=>$field)
{
if (!array_key_exists('effective_value',$field))
{
$all_visible=false;
continue;
}
// Do field details if it's visible, or if it is the first (name) field, or if it is our order field
/*if (($field['cf_visible']==1) || ($i==0) || ($order_by===$i)) Actually we always want the data even if it's not visible, especially for catalogues */
{
// Value to show
$ev=$field['effective_value'];
$dereference_ev=is_object($field['effective_value'])?$field['effective_value']->evaluate():$field['effective_value'];
$ob=get_fields_hook($field['cf_type']);
if (($i==0) && ($catalogue['c_display_type']==C_DT_TITLELIST))
{
$use_ev=$ev;
} else
{
$use_ev=$ob->render_field_value($field,$ev,$i,$only_fields);
}
// Special case for access to raw thumbnail
if ($field['cf_type']=='picture')
{
if ((!is_null($ev)) && ($dereference_ev!=''))
{
require_code('images');
$map['FIELD_'.strval($i).'_THUMB']=do_image_thumb($dereference_ev,($i==0)?'':(is_object($map['FIELD_0'])?$map['FIELD_0']->evaluate():$map['FIELD_0']),false,false);
} else
{
$map['FIELD_'.strval($i).'_THUMB']= new ocp_tempcode();
}
$map['_FIELD_'.strval($field['id']).'_THUMB']=$map['FIELD_'.strval($i).'_THUMB'];
}
// Different ways of accessing the main field value, and pure version of it
$map['FIELD_'.strval($i)]=$use_ev;
$map['_FIELD_'.strval($field['id'])]=$use_ev;
$map['FIELD_'.strval($i).'_PLAIN']=$ev;
$map['_FIELD_'.strval($field['id']).'_PLAIN']=$ev;
if (array_key_exists('effective_value_pure',$field))
{
$map['FIELD_'.strval($i).'_PURE']=$field['effective_value_pure'];
$map['_FIELD_'.strval($field['id']).'_PURE']=$field['effective_value_pure'];
}
$field_name=get_translated_text($field['cf_name']);
$map['FIELDNAME_'.strval($i)]=$field_name;
$fields_2d[]=array('NAME'=>$field_name,'VALUE'=>$use_ev);
$field_type=$field['cf_type'];
$map['FIELDTYPE_'.strval($i)]=$field_type;
// If the field should be shown, show it
if (($view_type=='PAGE') || (($field['cf_put_in_category']==1) && ($view_type=='CATEGORY')) || (($field['cf_put_in_search']==1) && ($view_type=='SEARCH')))
{
$use_ev_enhanced=$use_ev;
if (($field['cf_visible']==1) || ($i==0))
{
$f=array('ENTRYID'=>strval($id),'CATALOGUE'=>$catalogue_name,'TYPE'=>$field['cf_type'],'FIELD'=>$field_name,'FIELDID'=>strval($i),'_FIELDID'=>strval($field['id']),'FIELDTYPE'=>$field_type,'VALUE_PLAIN'=>$ev,'VALUE'=>$use_ev_enhanced);
$_field=do_template('CATALOGUE_'.$tpl_set.'_FIELDMAP_ENTRY_FIELD',$f,NULL,false,'CATALOGUE_DEFAULT_FIELDMAP_ENTRY_FIELD');
$map['FIELDS']->attach($_field);
$_field=do_template('CATALOGUE_'.$tpl_set.'_GRID_ENTRY_FIELD',$f,NULL,false,'CATALOGUE_DEFAULT_GRID_ENTRY_FIELD');
$map['FIELDS_GRID']->attach($_field);
$_field=do_template('CATALOGUE_'.$tpl_set.'_TABULAR_ENTRY_FIELD',$f,NULL,false,'CATALOGUE_DEFAULT_TABULAR_ENTRY_FIELD');
$map['FIELDS_TABULAR']->attach($_field);
}
} else $all_visible=false;
$fields_1d[]=$field;
}
if (!(($field['cf_visible']==1) || ($i==0) || ($order_by===$i))) $all_visible=false;
}
$map['FIELDS_1D']=$fields_1d;
$map['FIELDS_2D']=$fields_2d;
// Admin functions
if ((has_actual_page_access(NULL,'cms_catalogues',NULL,NULL)) && (has_edit_permission('mid',get_member(),$entry['ce_submitter'],'cms_catalogues',array('catalogues_catalogue',$catalogue_name,'catalogues_category',$entry['cc_id']))))
{
$map['EDIT_URL']=build_url(array('page'=>'cms_catalogues','type'=>'_edit_entry','catalogue_name'=>$catalogue_name,'id'=>$id),get_module_zone('cms_catalogues'));
} else $map['EDIT_URL']='';
// Various bits of meta data
$map['SUBMITTER']=strval($entry['ce_submitter']);
$map['VIEWS']=strval($entry['ce_views']);
$map['ADD_DATE_RAW']=strval($entry['ce_add_date']);
$map['EDIT_DATE_RAW']=is_null($entry['ce_edit_date'])?'':strval($entry['ce_edit_date']);
$map['ADD_DATE']=get_timezoned_date($entry['ce_add_date']);
$map['EDIT_DATE']=get_timezoned_date($entry['ce_edit_date']);
$map['ID']=strval($id);
$map['CATALOGUE']=$catalogue_name;
$map['CAT']=strval($entry['cc_id']);
if ((get_option('is_on_comments')=='1') && (!has_no_forum()) && ($entry['allow_comments']>=1)) $map['COMMENT_COUNT']='1';
// Feedback
require_code('feedback');
$c_value=array_key_exists('FIELD_0_PLAIN_PURE',$map)?$map['FIELD_0_PLAIN_PURE']:$map['FIELD_0_PLAIN'];
if (is_object($c_value)) $c_value=$c_value->evaluate();
$url_map=array('page'=>'catalogues','type'=>'entry','id'=>$id);
if (get_page_name()=='catalogues') $url_map+=propagate_ocselect();
$self_url=build_url($url_map,get_module_zone('catalogues'),NULL,false,false,true);
if (($feedback_details) || ($only_fields!==array(0)))
{
$map['RATING']=($entry['allow_rating']==1)?display_rating($self_url,$c_value,'catalogues__'.$catalogue_name,strval($id),'RATING_INLINE_STATIC',$entry['ce_submitter']):new ocp_tempcode();
}
if ($feedback_details)
{
list($map['RATING_DETAILS'],$map['COMMENT_DETAILS'],$map['TRACKBACK_DETAILS'])=embed_feedback_systems(
'catalogues__'.$catalogue_name,
strval($id),
$entry['allow_rating'],
$entry['allow_comments'],
$entry['allow_trackbacks'],
$entry['ce_validated'],
$entry['ce_submitter'],
$self_url,
$c_value,
get_value('comment_forum__catalogues__'.$catalogue_name)
);
}
// Link to view entry
if ((get_option('is_on_comments')=='1') && ($entry['allow_comments']>=1) || (get_option('is_on_rating')=='1') && ($entry['allow_rating']==1) || (get_option('is_on_trackbacks')=='1') && ($entry['allow_trackbacks']==1) || (!$all_visible))
{
$url_map=array('page'=>'catalogues','type'=>'entry','id'=>$id,'root'=>($root==-1)?NULL:$root);
if (get_page_name()=='catalogues') $url_map+=propagate_ocselect();
$map['VIEW_URL']=build_url($url_map,get_module_zone('catalogues'));
} else
{
$map['VIEW_URL']='';
}
// Breadcrumbs
if ($breadcrumbs_details)
{
$map['BREADCRUMBS']='';
if (($catalogue['c_is_tree']==1) && (is_null($only_fields)))
{
$breadcrumbs=catalogue_category_breadcrumbs($entry['cc_id'],$root,false);
$map['BREADCRUMBS']=$breadcrumbs;
}
}
return $map;
}
/**
* Get a nice, formatted, XHTML list of all the catalogues.
*
* @param ?ID_TEXT The name of the currently selected catalogue (NULL: none selected)
* @param boolean If there are too many to list prefer to get ones with entries rather than just the newest
* @param boolean Whether to only show catalogues that can be submitted to
* @return tempcode Catalogue selection list
*/
function nice_get_catalogues($it=NULL,$prefer_ones_with_entries=false,$only_submittable=false)
{
$query='SELECT c.* FROM '.get_table_prefix().'catalogues c';
if ($prefer_ones_with_entries)
{
if (can_arbitrary_groupby())
$query.=' JOIN '.get_table_prefix().'catalogue_entries e ON e.c_name=c.c_name GROUP BY c.c_name';
}
$query.=' ORDER BY c_add_date DESC';
$rows=$GLOBALS['SITE_DB']->query($query,100/*reasonable limit*/);
if (count($rows)==100) attach_message(do_lang_tempcode('TOO_MUCH_CHOOSE__ALPHABETICAL',escape_html(integer_format(100))),'warn');
$out=new ocp_tempcode();
foreach ($rows as $row)
{
if (substr($row['c_name'],0,1)=='_') continue;
if (!has_category_access(get_member(),'catalogues_catalogue',$row['c_name'])) continue;
if (($only_submittable) && (!has_specific_permission(get_member(),'submit_midrange_content','cms_catalogues',array('catalogues_catalogue',$row['c_name'])))) continue;
if (($row['c_ecommerce']==0) || (addon_installed('shopping')))
{
$selected=($row['c_name']==$it);
$out->attach(form_input_list_entry($row['c_name'],$selected,get_translated_text($row['c_title'])));
}
}
return $out;
}
/**
* Get the values for the specified fields, for the stated catalogue entry.
*
* @param ?ID_TEXT The catalogue name we are getting an entry in (NULL: lookup)
* @param mixed The ID of the entry we are getting OR the row
* @param ?array A list of fields that we are limiting ourselves to (NULL: get ALL fields)
* @param ?array The database rows for the fields for this catalogue (NULL: find them)
* @param boolean Whether to order the fields in their natural database order
* @param ID_TEXT The view type we're doing
* @set PAGE SEARCH CATEGORY
* @return array A list of maps (each field for the entry gets a map), where each map contains 'effective_value' (the value for the field). Some maps get additional fields (effective_value_nontrans, effective_value_pure), depending on the field type
*/
function get_catalogue_entry_field_values($catalogue_name,$entry_id,$only_fields=NULL,$fields=NULL,$natural_order=false,$view_type='PAGE')
{
global $CAT_FIELDS_CACHE;
if (is_null($fields))
{
if ((isset($CAT_FIELDS_CACHE[$catalogue_name])) && (!$natural_order))
{
$fields=$CAT_FIELDS_CACHE[$catalogue_name];
} else
{
if (is_null($catalogue_name)) $catalogue_name=$GLOBALS['SITE_DB']->query_value('catalogue_entries','c_name',array('id'=>$entry_id));
$fields=$GLOBALS['SITE_DB']->query_select('catalogue_fields',array('*'),array('c_name'=>$catalogue_name),'ORDER BY '.($natural_order?'id':'cf_order'));
}
}
if (!$natural_order)
$CAT_FIELDS_CACHE[$catalogue_name]=$fields;
require_code('fields');
// Work out an ID filter for what fields to show
$only_field_ids=mixed();
if (get_value('catalogue_limit_cat_field_load__'.$catalogue_name)==='1')
{
$only_field_ids=array();
foreach ($fields as $i=>$field)
{
$field_id=$field['id'];
if ((!is_null($only_fields)) && (!in_array($i,$only_fields))) continue;
if ($field['cf_defines_order']==0)
{
if (($view_type=='CATEGORY') && ($field['cf_put_in_category']==0)) continue;
if (($view_type=='SEARCH') && ($field['cf_put_in_search']==0)) continue;
}
$only_field_ids[]=$field_id;
}
}
foreach ($fields as $i=>$field)
{
$field_id=$field['id'];
if ((!is_null($only_fields)) && (!in_array($i,$only_fields))) continue;
$ob=get_fields_hook($field['cf_type']);
list($raw_type,,$type)=$ob->get_field_value_row_bits($field);
if (is_null($raw_type)) $raw_type=$field['cf_type'];
switch ($raw_type)
{
case 'short_trans':
$fields[$i]['effective_value_nontrans']=_get_catalogue_entry_field($field_id,$entry_id,'short_trans',$only_field_ids);
if (is_null($fields[$i]['effective_value_nontrans']))
{
$fields[$i]['effective_value']=do_lang_tempcode('INTERNAL_ERROR');
$fields[$i]['effective_value_pure']=do_lang('INTERNAL_ERROR');
break;
}
$fields[$i]['effective_value']=get_translated_tempcode(intval($fields[$i]['effective_value_nontrans']));
$fields[$i]['effective_value_pure']=get_translated_text(intval($fields[$i]['effective_value_nontrans']));
break;
case 'long_trans':
$fields[$i]['effective_value_nontrans']=_get_catalogue_entry_field($field_id,$entry_id,'long_trans',$only_field_ids);
if (is_null($fields[$i]['effective_value_nontrans']))
{
$fields[$i]['effective_value']=do_lang_tempcode('INTERNAL_ERROR');
$fields[$i]['effective_value_pure']=do_lang('INTERNAL_ERROR');
break;
}
$fields[$i]['effective_value']=get_translated_tempcode(intval($fields[$i]['effective_value_nontrans']));
$fields[$i]['effective_value_pure']=get_translated_text(intval($fields[$i]['effective_value_nontrans']));
break;
case 'long_text':
$fields[$i]['effective_value_pure']=_get_catalogue_entry_field($field_id,$entry_id,'long',$only_field_ids);
$fields[$i]['effective_value']=$fields[$i]['effective_value_pure'];
if (is_null($fields[$i]['effective_value']))
{
$fields[$i]['effective_value']=do_lang_tempcode('INTERNAL_ERROR');
$fields[$i]['effective_value_pure']=do_lang('INTERNAL_ERROR');
break;
}
break;
case 'short_text':
$fields[$i]['effective_value_pure']=_get_catalogue_entry_field($field_id,$entry_id,$only_field_ids);
$fields[$i]['effective_value']=$fields[$i]['effective_value_pure'];
if (is_null($fields[$i]['effective_value']))
{
$fields[$i]['effective_value']=do_lang_tempcode('NA_EM');
$fields[$i]['effective_value_pure']=do_lang('NA');
break;
}
break;
case 'long_unescaped':
$fields[$i]['effective_value']=_get_catalogue_entry_field($field_id,$entry_id,'long',$only_field_ids);
if (is_null($fields[$i]['effective_value']))
{
$fields[$i]['effective_value']=do_lang_tempcode('NA_EM');
$fields[$i]['effective_value_pure']=do_lang('NA');
break;
}
break;
case 'short_unescaped':
case 'float_unescaped':
case 'integer_unescaped':
$fields[$i]['effective_value']=_get_catalogue_entry_field($field_id,$entry_id,$type,$only_field_ids);
if (is_null($fields[$i]['effective_value']))
{
$fields[$i]['effective_value']=do_lang_tempcode('NA_EM');
$fields[$i]['effective_value_pure']=do_lang('NA');
break;
}
break;
default:
warn_exit(do_lang_tempcode('INTERNAL_ERROR'));
}
}
return $fields;
}
/**
* Get the value for the specified field, for the stated catalogue entry.
*
* @param AUTO_LINK The ID of the field we are getting
* @param mixed The ID of the entry we are getting for OR the row
* @param ID_TEXT The type of field
* @set short long
* @param ?array A list of field IDs that we are limiting ourselves to (NULL: get ALL fields)
* @return string The value
*/
function _get_catalogue_entry_field($field_id,$entry_id,$type='short',$only_field_ids=NULL)
{
if (is_array($entry_id)) $entry_id=$entry_id['id'];