33namespace Scriptotek \Marc \Fields ;
44
55use File_MARC_Field ;
6+ use File_MARC_Subfield ;
67use JsonSerializable ;
78use Scriptotek \Marc \MagicAccess ;
89use Scriptotek \Marc \Record ;
910
11+ /**
12+ * The MARC field wrapper.
13+ *
14+ * We wrap File_MARC_Field rather than extend it, just like in our Record
15+ * class. File_MARC_Field has two known subclasses, namely File_MARC_Data_Field
16+ * and File_MARC_Control_Field.
17+ *
18+ * Methods on the wrapped field that are not implemented here may be accessed
19+ * using magic method calls, or through `getField()`. Method tags are included
20+ * below to aid IDE code hinting, but using the getter will give you better
21+ * code
22+ * hinting and documentation.
23+ *
24+ * @method string getTag()
25+ * @method string setTag()
26+ * @method bool isEmpty()
27+ * @method bool isControlField()
28+ * @method bool isDataField()
29+ * @method string toRaw()
30+ * @method formatField(array $exclude = array('2'))
31+ *
32+ * FIXME: These methods are just implemented in File_MARC_Data_Field and not in
33+ * File_MARC_Field or File_MARC_Control_Field, so they may not always be
34+ * available:
35+ *
36+ * @method File_MARC_Subfield appendSubfield(File_MARC_Subfield $new_subfield)
37+ * @method File_MARC_Subfield prependSubfield(File_MARC_Subfield $new_subfield)
38+ * @method File_MARC_Subfield insertSubfield(File_MARC_Subfield $new_field, File_MARC_Subfield $existing_field, bool $before = false)
39+ * @method int addSubfields(array $subfields)
40+ * @method deleteSubfield(File_MARC_Subfield $subfield)
41+ * @method string getIndicator(int $ind)
42+ * @method string setIndicator(int $ind, string $value)
43+ * @method string getSubfield(string $code = null, bool $pcre = null)
44+ * @method array getSubfields(string $code = null, bool $pcre = null)
45+ * @method string getContents(string $joinChar = '')
46+ *
47+ * FIXME: These methods are just implemented in File_MARC_Control_Field and not
48+ * in File_MARC_Field or File_MARC_Data_Field, so they may not always be
49+ * available:
50+ *
51+ * @method string getData()
52+ * @method bool setData(string $data)
53+ */
1054class Field implements JsonSerializable
1155{
1256 use SerializableField, MagicAccess;
1357
1458 /**
15- * @var array List of properties to be included when serializing the record using the `toArray()` method.
59+ * @var array List of properties to be included when serializing the record
60+ * using the `toArray()` method.
1661 */
1762 public $ properties = [];
1863
64+ /**
65+ * The characters used to separate values of a subfield.
66+ *
67+ * @var string
68+ */
1969 public static $ glue = ' : ' ;
70+
71+ /**
72+ * Whether to strip punctuation from the end of some field values.
73+ *
74+ * @var bool
75+ */
2076 public static $ chopPunctuation = true ;
2177
78+ /**
79+ * The wrapped field.
80+ *
81+ * @var \File_MARC_Field
82+ */
2283 protected $ field ;
2384
85+ /**
86+ * Field constructor.
87+ *
88+ * @param \File_MARC_Field $field
89+ * The field to wrap.
90+ */
2491 public function __construct (File_MARC_Field $ field )
2592 {
2693 $ this ->field = $ field ;
@@ -36,16 +103,41 @@ public function getField()
36103 return $ this ->field ;
37104 }
38105
106+ /**
107+ * Delegate all unknown method calls to the wrapped field.
108+ *
109+ * @param string $name
110+ * The name of the method being called.
111+ * @param array $args
112+ * The arguments being passed to the method.
113+ *
114+ * @return mixed
115+ */
39116 public function __call ($ name , $ args )
40117 {
41118 return call_user_func_array ([$ this ->field , $ name ], $ args );
42119 }
43120
121+ /**
122+ * Get a string representation of this field.
123+ *
124+ * @return string
125+ */
44126 public function __toString ()
45127 {
46128 return $ this ->field ->__toString ();
47129 }
48130
131+ /**
132+ * Remove extra whitespace and punctuation from field values.
133+ *
134+ * @param string $value
135+ * The value to clean.
136+ * @param array $options
137+ * A list of options. Currently only the chopPunctuation key is used.
138+ *
139+ * @return string
140+ */
49141 protected function clean ($ value , $ options = [])
50142 {
51143 $ chopPunctuation = isset ($ options ['chopPunctuation ' ]) ? $ options ['chopPunctuation ' ] : static ::$ chopPunctuation ;
@@ -57,15 +149,20 @@ protected function clean($value, $options = [])
57149 }
58150
59151 /**
152+ * Extract values from subfields of this field.
153+ *
60154 * @param string|string[] $codes
61- * @return array
155+ * The subfield code or an array of such codes.
156+ * @return string[]
157+ * The values that were contained in the requested subfields.
62158 */
63159 protected function getSubfieldValues ($ codes )
64160 {
65161 if (!is_array ($ codes )) {
66162 $ codes = [$ codes ];
67163 }
68164 $ parts = [];
165+ /** @var \File_MARC_Subfield $sf */
69166 foreach ($ this ->field ->getSubfields () as $ sf ) {
70167 if (in_array ($ sf ->getCode (), $ codes )) {
71168 $ parts [] = trim ($ sf ->getData ());
@@ -79,8 +176,11 @@ protected function getSubfieldValues($codes)
79176 * Return concatenated string of the given subfields.
80177 *
81178 * @param string[] $codes
82- * @param array $options
179+ * The subfield codes to retrieve.
180+ * @param array $options
181+ * Options to pass to the `clean` method.
83182 * @return string
183+ * The concatenated subfield values.
84184 */
85185 protected function toString ($ codes , $ options = [])
86186 {
@@ -89,19 +189,22 @@ protected function toString($codes, $options = [])
89189 }
90190
91191 /**
92- * Return a line MARC representation of the field. If the field is deleted,
93- * null is returned.
192+ * Get a line MARC representation of the field.
94193 *
95- * @param string $sep Subfield separator character, defaults to '$'
96- * @param string $blank Blank indicator character, defaults to ' '
97- * @return string|null.
194+ * @param string $sep
195+ * Subfield separator character, defaults to '$'
196+ * @param string $blank
197+ * Blank indicator character, defaults to ' '
198+ * @return string|null
199+ * A line MARC representation of the field or NULL if the field is empty.
98200 */
99201 public function asLineMarc ($ sep = '$ ' , $ blank = ' ' )
100202 {
101203 if ($ this ->field ->isEmpty ()) {
102204 return null ;
103205 }
104206 $ subfields = [];
207+ /** @var \File_MARC_Subfield $sf */
105208 foreach ($ this ->field ->getSubfields () as $ sf ) {
106209 $ subfields [] = $ sep . $ sf ->getCode () . ' ' . $ sf ->getData ();
107210 }
@@ -122,30 +225,44 @@ public function asLineMarc($sep = '$', $blank = ' ')
122225 * Return the data value of the *first* subfield with a given code.
123226 *
124227 * @param string $code
228+ * The subfield identifier.
125229 * @param mixed $default
230+ * The fallback value to return if the subfield does not exist.
126231 * @return mixed
127232 */
128233 public function sf ($ code , $ default = null )
129234 {
130-
131235 // In PHP, ("a" == 0) will evaluate to TRUE, so it's actually very important that we ensure type here!
132236 $ code = (string ) $ code ;
133237
134- $ subfield = $ this ->getSubfield ($ code );
238+ /** @var \File_MARC_Subfield $subfield */
239+ $ subfield = $ this ->field ->getSubfield ($ code );
135240 if (!$ subfield ) {
136241 return $ default ;
137242 }
138243
139244 return trim ($ subfield ->getData ());
140245 }
141246
247+ /**
248+ * TODO: document this function.
249+ *
250+ * @param $map
251+ * TODO: ?
252+ * @param bool $includeNullValues
253+ * TODO: ?
254+ *
255+ * @return array
256+ * TODO: ?
257+ */
142258 public function mapSubFields ($ map , $ includeNullValues = false )
143259 {
144260 $ o = [];
145261 foreach ($ map as $ code => $ prop ) {
146262 $ value = $ this ->sf ($ code );
147263
148- foreach ($ this ->getSubfields () as $ q ) {
264+ /** @var \File_MARC_Subfield $q */
265+ foreach ($ this ->field ->getSubfields () as $ q ) {
149266 if ($ q ->getCode () === $ code ) {
150267 $ value = $ q ->getData ();
151268 }
@@ -158,7 +275,20 @@ public function mapSubFields($map, $includeNullValues = false)
158275 return $ o ;
159276 }
160277
161- public static function makeFieldObject (Record $ record , $ tag , $ pcre =false )
278+ /**
279+ * TODO: document this function.
280+ *
281+ * @param \Scriptotek\Marc\Record $record
282+ * TODO: ?
283+ * @param string $tag
284+ * The tag name.
285+ * @param bool $pcre
286+ * If true, match as a regular expression.
287+ *
288+ * @return \Scriptotek\Marc\Fields\Field
289+ * TODO: ?
290+ */
291+ public static function makeFieldObject (Record $ record , $ tag , $ pcre = false )
162292 {
163293 $ field = $ record ->getField ($ tag , $ pcre );
164294
@@ -167,10 +297,22 @@ public static function makeFieldObject(Record $record, $tag, $pcre=false)
167297 return $ field ? new static ($ field ->getField ()) : null ;
168298 }
169299
170- public static function makeFieldObjects (Record $ record , $ tag , $ pcre =false )
300+ /**
301+ * TODO: document this function.
302+ *
303+ * @param \Scriptotek\Marc\Record $record
304+ * TODO: ?
305+ * @param string $tag
306+ * The tag name.
307+ * @param bool $pcre
308+ * If true, match as a regular expression.
309+ *
310+ * @return \Scriptotek\Marc\Fields\Field[]
311+ * TODO: ?
312+ */
313+ public static function makeFieldObjects (Record $ record , $ tag , $ pcre = false )
171314 {
172- return array_map (function ($ field ) {
173-
315+ return array_map (function (Field $ field ) {
174316 // Note: `new static()` is a way of creating a new instance of the
175317 // called class using late static binding.
176318 return new static ($ field ->getField ());
0 commit comments