@prefix sioc: <http://rdfs.org/sioc/ns#> .
@prefix dc: <http://purl.org/dc/elements/1.1/> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix content: <http://purl.org/rss/1.0/modules/content/> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .

<https://lhero.org/?p=624>
  a sioc:Post ;
  dc:title "LH Profile Page" ;
  dcterms:identifier 624 ;
  dc:modified "2026-09-22T00:30:05Z"^^xsd:dateTime ;
  dc:created "2016-06-25T02:17:31Z"^^xsd:dateTime ;
  sioc:link <https://lhero.org/portfolio/lh-profile-page/> ;
  sioc:has_creator <https://lhero.org/author/1/#account> ;
  sioc:has_container <https://lhero.org/#posts> ;
  content:encoded "<ul class=\"lh_portfolio-meta\"><li><strong>Type:</strong> Plugin</li></ul><p class=\"wp-block-paragraph\">LH Profile Page owns a core set of user profile fields for LocalHero sites &#8211; phone, secondary phone, gender, birthdate, street address, town, postcode, state/province, and country &#8211; stored as plain WordPress user meta rather than a custom database table. It also integrates these fields into BuddyPress&#039;s xProfile system as &quot;faux&quot; field types, so they can be added to a BuddyPress profile field group and edited through the normal xProfile UI while the underlying data stays in ordinary <code>wp_usermeta</code>.</p><p class=\"wp-block-paragraph\">This makes the plugin migration-critical: any site owner leaving LocalHero needs to understand this data model to export or migrate their members&#039; profile data, since a large number of other <code>lh-</code> plugins (check-ins, CRM, group invites, group reports, vcard export, CSV import, &quot;Users Insights&quot;) all read or write these same fields.</p><h2 class=\"wp-block-heading\">Key features</h2><ul class=\"wp-block-list\"><li><strong>Per-field validation.</strong> Phone numbers are validated to E.164 format (<code>giggsey/libphonenumber-for-php-lite</code>); gender is restricted to a fixed value set; birthdate is normalised to a consistent <code>Y-m-d</code> date string. Each validated field is registered via WordPress&#039;s own <code>register_meta()</code>, so the validation applies to <em>any</em> direct write to that meta key &#8211; not just writes that go through this plugin&#039;s own forms.</li><li><strong>Front-end and back-end editing.</strong> A WordPress admin user-edit screen section, a front-end shortcode form (<code>[lh_profile_admin_form]</code>), and full BuddyPress xProfile integration all edit the same underlying data.</li><li><strong>A field-class architecture.</strong> What was originally one large &quot;god class&quot; has been progressively split into a dedicated class per field (phone, gender, birthdate, and each of the five address fields, plus the three name fields), each with its own file, while keeping the original class&#039;s public methods working via back-compat proxy shims &#8211; see Field Class Architecture.</li></ul><ul class=\"lh_portfolio-doc-toc\"><li><a href=\"https://lhero.org/portfolio/lh-profile-page/field-class-architecture/\">Field Class Architecture</a></li><li><a href=\"https://lhero.org/portfolio/lh-profile-page/database-schema/\">Database Schema</a></li><li><a href=\"https://lhero.org/portfolio/lh-profile-page/admin-interfaces-shortcodes/\">Admin Interfaces &#038; Shortcodes</a></li><li><a href=\"https://lhero.org/portfolio/lh-profile-page/hooks-reference/\">Hooks Reference</a></li><li><a href=\"https://lhero.org/portfolio/lh-profile-page/mcp-abilities/\">MCP Abilities</a></li><li><a href=\"https://lhero.org/portfolio/lh-profile-page/cron-jobs/\">Cron Jobs</a></li><li><a href=\"https://lhero.org/portfolio/lh-profile-page/architectural-notes-gotchas/\">Architectural Notes &#038; Gotchas</a></li><li><a href=\"https://lhero.org/portfolio/lh-profile-page/changelog/\">Changelog</a></li></ul>"^^rdf:XMLLiteral ;
  sioc:content "Type: PluginLH Profile Page owns a core set of user profile fields for LocalHero sites &#8211; phone, secondary phone, gender, birthdate, street address, town, postcode, state/province, and country &#8211; stored as plain WordPress user meta rather than a custom database table. It also integrates these fields into BuddyPress&#039;s xProfile system as &quot;faux&quot; field types, so they can be added to a BuddyPress profile field group and edited through the normal xProfile UI while the underlying data stays in ordinary wp_usermeta.This makes the plugin migration-critical: any site owner leaving LocalHero needs to understand this data model to export or migrate their members&#039; profile data, since a large number of other lh- plugins (check-ins, CRM, group invites, group reports, vcard export, CSV import, &quot;Users Insights&quot;) all read or write these same fields.Key featuresPer-field validation. Phone numbers are validated to E.164 format (giggsey/libphonenumber-for-php-lite); gender is restricted to a fixed value set; birthdate is normalised to a consistent Y-m-d date string. Each validated field is registered via WordPress&#039;s own register_meta(), so the validation applies to any direct write to that meta key &#8211; not just writes that go through this plugin&#039;s own forms.Front-end and back-end editing. A WordPress admin user-edit screen section, a front-end shortcode form ([lh_profile_admin_form]), and full BuddyPress xProfile integration all edit the same underlying data.A field-class architecture. What was originally one large &quot;god class&quot; has been progressively split into a dedicated class per field (phone, gender, birthdate, and each of the five address fields, plus the three name fields), each with its own file, while keeping the original class&#039;s public methods working via back-compat proxy shims &#8211; see Field Class Architecture.Field Class ArchitectureDatabase SchemaAdmin Interfaces &#038; ShortcodesHooks ReferenceMCP AbilitiesCron JobsArchitectural Notes &#038; GotchasChangelog" ;
  sioc:topic <https://lhero.org/lh_portfolio-type/plugin/>, <https://lhero.org/?taxonomy=lh_portfolio-tags&term=users>, <https://lhero.org/?taxonomy=lh_portfolio-tags&term=user>, <https://lhero.org/?taxonomy=lh_portfolio-tags&term=meta>, <https://lhero.org/?taxonomy=lh_portfolio-tags&term=profile>, <https://lhero.org/?taxonomy=lh_portfolio-tags&term=front-end>, <https://lhero.org/?taxonomy=author&term=cap-1> .

<https://lhero.org/author/1/#account> rdfs:seeAlso <https://lhero.org/author/1/?feed=lhrdf&format=turtle> .
<https://lhero.org/lh_portfolio-type/plugin/> rdfs:seeAlso <https://lhero.org/lh_portfolio-type/plugin/?feed=lhrdf&format=turtle> .
<https://lhero.org/?taxonomy=lh_portfolio-tags&term=users> rdfs:seeAlso <https://lhero.org/?taxonomy=lh_portfolio-tags&term=users&feed=lhrdf&format=turtle> .
<https://lhero.org/?taxonomy=lh_portfolio-tags&term=user> rdfs:seeAlso <https://lhero.org/?taxonomy=lh_portfolio-tags&term=user&feed=lhrdf&format=turtle> .
<https://lhero.org/?taxonomy=lh_portfolio-tags&term=meta> rdfs:seeAlso <https://lhero.org/?taxonomy=lh_portfolio-tags&term=meta&feed=lhrdf&format=turtle> .
<https://lhero.org/?taxonomy=lh_portfolio-tags&term=profile> rdfs:seeAlso <https://lhero.org/?taxonomy=lh_portfolio-tags&term=profile&feed=lhrdf&format=turtle> .
<https://lhero.org/?taxonomy=lh_portfolio-tags&term=front-end> rdfs:seeAlso <https://lhero.org/?taxonomy=lh_portfolio-tags&term=front-end&feed=lhrdf&format=turtle> .
<https://lhero.org/?taxonomy=author&term=cap-1> rdfs:seeAlso <https://lhero.org/?taxonomy=author&term=cap-1&feed=lhrdf&format=turtle> .
