diff --git a/composer.json b/composer.json
index a800dbcaf53af96ec3d856bbd2ecb8c98d99a037..2db2bf6f3c3fa43e289842a6dc9125ca10c05459 100644
--- a/composer.json
+++ b/composer.json
@@ -125,6 +125,7 @@
         "drupal/module_filter": "^3.1",
         "drupal/paragraphs": "1.6",
         "drupal/pathauto": "1.0",
+        "drupal/realname": "^1.0@RC",
         "drupal/redis": "1.0",
         "drupal/roleassign": "^1.0@alpha",
         "drupal/scheduler": "1.0",
diff --git a/composer.lock b/composer.lock
index df7974fdbb48ce22a00ab15944f644d45f6adf3b..d42fac30dfb34ccb96b9ea9819374ba606cd6649 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "content-hash": "37d0639fa7a21db15c16f008e672a3db",
+    "content-hash": "8e0a476fe788ae140996a08bbf6f6798",
     "packages": [
         {
             "name": "alchemy/zippy",
@@ -4864,8 +4864,7 @@
             "homepage": "https://www.drupal.org/project/migrate_devel",
             "support": {
                 "source": "http://cgit.drupalcode.org/migrate_devel"
-            },
-            "time": "2017-06-25T23:46:13+00:00"
+            }
         },
         {
             "name": "drupal/migrate_plus",
@@ -5192,6 +5191,83 @@
                 "source": "http://cgit.drupalcode.org/pathauto"
             }
         },
+        {
+            "name": "drupal/realname",
+            "version": "1.0.0-rc2",
+            "source": {
+                "type": "git",
+                "url": "https://git.drupal.org/project/realname",
+                "reference": "8.x-1.0-rc2"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://ftp.drupal.org/files/projects/realname-8.x-1.0-rc2.zip",
+                "reference": "8.x-1.0-rc2",
+                "shasum": "f5bd7f98fdf17ef3b7d8eb3c1f9a5c043f121354"
+            },
+            "require": {
+                "drupal/core": "~8.0",
+                "drupal/token": "^1.0.0-alpha2"
+            },
+            "type": "drupal-module",
+            "extra": {
+                "branch-alias": {
+                    "dev-1.x": "1.x-dev"
+                },
+                "drupal": {
+                    "version": "8.x-1.0-rc2",
+                    "datestamp": "1548970380",
+                    "security-coverage": {
+                        "status": "not-covered",
+                        "message": "RC releases are not covered by Drupal security advisories."
+                    }
+                }
+            },
+            "notification-url": "https://packages.drupal.org/8/downloads",
+            "license": [
+                "GPL-2.0+"
+            ],
+            "authors": [
+                {
+                    "name": "hass",
+                    "homepage": "https://www.drupal.org/u/hass"
+                },
+                {
+                    "name": "See other contributors",
+                    "homepage": "https://www.drupal.org/node/266280/committers"
+                },
+                {
+                    "name": "coderintherye",
+                    "homepage": "https://www.drupal.org/user/297478"
+                },
+                {
+                    "name": "hass",
+                    "homepage": "https://www.drupal.org/user/85918"
+                },
+                {
+                    "name": "rmiddle",
+                    "homepage": "https://www.drupal.org/user/192183"
+                },
+                {
+                    "name": "theamoeba",
+                    "homepage": "https://www.drupal.org/user/251700"
+                },
+                {
+                    "name": "tkuldeep17",
+                    "homepage": "https://www.drupal.org/user/2498278"
+                },
+                {
+                    "name": "voxpelli",
+                    "homepage": "https://www.drupal.org/user/341713"
+                }
+            ],
+            "description": "Provides token-based name displays for users.",
+            "homepage": "https://www.drupal.org/project/realname",
+            "support": {
+                "source": "https://git.drupal.org/project/realname.git",
+                "issues": "https://www.drupal.org/project/issues/realname"
+            }
+        },
         {
             "name": "drupal/redis",
             "version": "1.0.0",
@@ -10771,6 +10847,7 @@
         "drupal/block_field": 15,
         "drupal/entity_clone": 10,
         "drupal/migrate_devel": 20,
+        "drupal/realname": 5,
         "drupal/roleassign": 15,
         "drupal/view_unpublished": 15
     },
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index b15ea72675fd919bca0e63fe690cec71e9c038b8..98462dba9d2a86da8046ac7b08ef466c5a869549 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -5352,6 +5352,85 @@
             "source": "http://cgit.drupalcode.org/pathauto"
         }
     },
+    {
+        "name": "drupal/realname",
+        "version": "1.0.0-rc2",
+        "version_normalized": "1.0.0.0-RC2",
+        "source": {
+            "type": "git",
+            "url": "https://git.drupal.org/project/realname",
+            "reference": "8.x-1.0-rc2"
+        },
+        "dist": {
+            "type": "zip",
+            "url": "https://ftp.drupal.org/files/projects/realname-8.x-1.0-rc2.zip",
+            "reference": "8.x-1.0-rc2",
+            "shasum": "f5bd7f98fdf17ef3b7d8eb3c1f9a5c043f121354"
+        },
+        "require": {
+            "drupal/core": "~8.0",
+            "drupal/token": "^1.0.0-alpha2"
+        },
+        "type": "drupal-module",
+        "extra": {
+            "branch-alias": {
+                "dev-1.x": "1.x-dev"
+            },
+            "drupal": {
+                "version": "8.x-1.0-rc2",
+                "datestamp": "1548970380",
+                "security-coverage": {
+                    "status": "not-covered",
+                    "message": "RC releases are not covered by Drupal security advisories."
+                }
+            }
+        },
+        "installation-source": "dist",
+        "notification-url": "https://packages.drupal.org/8/downloads",
+        "license": [
+            "GPL-2.0+"
+        ],
+        "authors": [
+            {
+                "name": "hass",
+                "homepage": "https://www.drupal.org/u/hass"
+            },
+            {
+                "name": "See other contributors",
+                "homepage": "https://www.drupal.org/node/266280/committers"
+            },
+            {
+                "name": "coderintherye",
+                "homepage": "https://www.drupal.org/user/297478"
+            },
+            {
+                "name": "hass",
+                "homepage": "https://www.drupal.org/user/85918"
+            },
+            {
+                "name": "rmiddle",
+                "homepage": "https://www.drupal.org/user/192183"
+            },
+            {
+                "name": "theamoeba",
+                "homepage": "https://www.drupal.org/user/251700"
+            },
+            {
+                "name": "tkuldeep17",
+                "homepage": "https://www.drupal.org/user/2498278"
+            },
+            {
+                "name": "voxpelli",
+                "homepage": "https://www.drupal.org/user/341713"
+            }
+        ],
+        "description": "Provides token-based name displays for users.",
+        "homepage": "https://www.drupal.org/project/realname",
+        "support": {
+            "source": "https://git.drupal.org/project/realname.git",
+            "issues": "https://www.drupal.org/project/issues/realname"
+        }
+    },
     {
         "name": "drupal/redis",
         "version": "1.0.0",
diff --git a/web/modules/realname/LICENSE.txt b/web/modules/realname/LICENSE.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d159169d1050894d3ea3b98e1c965c4058208fe1
--- /dev/null
+++ b/web/modules/realname/LICENSE.txt
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/web/modules/realname/README.txt b/web/modules/realname/README.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f23719d116b20726ea7d5f6bc18728b9a7ba9004
--- /dev/null
+++ b/web/modules/realname/README.txt
@@ -0,0 +1,55 @@
+CONTENTS OF THIS FILE
+---------------------
+
+* Introduction
+* Requirements
+* Installation
+* Configuration
+* Maintainers
+
+
+INTRODUCTION
+------------
+
+The Real name module allows the admin to choose fields from the user profile
+that will be used to add a "realname" element (method) to a user object.
+Hook_user is used to automatically add this to any user object that is loaded.
+
+
+* For a full description of the module visit
+  https://www.drupal.org/project/realname.
+
+* To submit bug reports and feature suggestions, or to track changes visit
+  https://www.drupal.org/project/issues/realname.
+
+
+REQUIREMENTS
+------------
+
+This module requires the following module:
+
+ * Token - https://www.drupal.org/project/token
+
+
+INSTALLATION
+------------
+
+Install the Real name module as you would normally install a contributed
+Drupal module. Visit https://www.drupal.org/node/1897420 for further
+information.
+
+
+CONFIGURATION
+-------------
+
+The settings page is at Administration >> Configuration >> People >> Real name.
+
+This pattern will be used to construct Realnames for all users.
+Note that if the pattern is changed: all current Realnames will be deleted and
+the list in the database will be rebuilt as needed.
+
+
+MAINTAINERS
+-----------
+
+* Alexander Hass (hass) - https://www.drupal.org/u/hass
diff --git a/web/modules/realname/composer.json b/web/modules/realname/composer.json
new file mode 100644
index 0000000000000000000000000000000000000000..027764245d4a77162631adb6e3c356d25260c244
--- /dev/null
+++ b/web/modules/realname/composer.json
@@ -0,0 +1,24 @@
+{
+  "name": "drupal/realname",
+  "description": "Provides token-based name displays for users.",
+  "type": "drupal-module",
+  "homepage": "https://www.drupal.org/project/realname",
+  "authors": [
+    {
+      "name": "hass",
+      "homepage": "https://www.drupal.org/u/hass"
+    },
+    {
+      "name": "See other contributors",
+      "homepage":"https://www.drupal.org/node/266280/committers"
+    }
+  ],
+  "support": {
+    "issues": "https://www.drupal.org/project/issues/realname",
+    "source": "https://git.drupal.org/project/realname.git"
+  },
+  "license": "GPL-2.0+",
+  "require": {
+    "drupal/token": "^1.0.0-alpha2"
+  }
+}
diff --git a/web/modules/realname/config/install/realname.settings.yml b/web/modules/realname/config/install/realname.settings.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9546e78dfacf086e45cbe9724b25942095689cdf
--- /dev/null
+++ b/web/modules/realname/config/install/realname.settings.yml
@@ -0,0 +1 @@
+pattern: '[user:account-name]'
diff --git a/web/modules/realname/config/install/system.action.realname_update_realname_action.yml b/web/modules/realname/config/install/system.action.realname_update_realname_action.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d46fa3c1c3999e9390186268fc154be429c7d5d8
--- /dev/null
+++ b/web/modules/realname/config/install/system.action.realname_update_realname_action.yml
@@ -0,0 +1,10 @@
+langcode: en
+status: true
+dependencies:
+  module:
+    - user
+id: realname_update_realname_action
+label: 'Update real names of the selected user(s)'
+type: user
+plugin: realname_update_realname_action
+configuration: {  }
diff --git a/web/modules/realname/config/schema/realname.schema.yml b/web/modules/realname/config/schema/realname.schema.yml
new file mode 100644
index 0000000000000000000000000000000000000000..f28a9ad837e89acc558b32108f0d02853c028c59
--- /dev/null
+++ b/web/modules/realname/config/schema/realname.schema.yml
@@ -0,0 +1,13 @@
+# Schema for the configuration files of the realname module.
+
+realname.settings:
+  type: config_object
+  label: 'Realname settings'
+  mapping:
+    pattern:
+      type: string
+      label: 'Realname pattern'
+
+action.configuration.realname_update_realname_action:
+  type: action_configuration_default
+  label: 'Update real name'
diff --git a/web/modules/realname/migrations/d6_realname_settings.yml b/web/modules/realname/migrations/d6_realname_settings.yml
new file mode 100644
index 0000000000000000000000000000000000000000..a3326fbc3d18025b0e1dff133edd9b399d7a3b1e
--- /dev/null
+++ b/web/modules/realname/migrations/d6_realname_settings.yml
@@ -0,0 +1,18 @@
+id: d6_realname_settings
+label: Realname 6 configuration
+migration_tags:
+  - Drupal 6
+  - Configuration
+source:
+  plugin: variable
+  variables:
+    - realname_pattern
+  source_module: realname
+process:
+  pattern:
+    plugin: realname_replace_token
+    source:
+      - realname_pattern
+destination:
+  plugin: config
+  config_name: realname.settings
diff --git a/web/modules/realname/migrations/d7_realname_settings.yml b/web/modules/realname/migrations/d7_realname_settings.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6b11af74df53070f23e4912637da27c10868653a
--- /dev/null
+++ b/web/modules/realname/migrations/d7_realname_settings.yml
@@ -0,0 +1,18 @@
+id: d7_realname_settings
+label: Realname 7 configuration
+migration_tags:
+  - Drupal 7
+  - Configuration
+source:
+  plugin: variable
+  variables:
+    - realname_pattern
+  source_module: realname
+process:
+  pattern:
+    plugin: realname_replace_token
+    source:
+      - realname_pattern
+destination:
+  plugin: config
+  config_name: realname.settings
diff --git a/web/modules/realname/realname.api.php b/web/modules/realname/realname.api.php
new file mode 100644
index 0000000000000000000000000000000000000000..09e813e57c599658ebd21c2cea19b57b41c03304
--- /dev/null
+++ b/web/modules/realname/realname.api.php
@@ -0,0 +1,58 @@
+<?php
+
+/**
+ * @file
+ * Hooks provided by the Real name module.
+ */
+
+/**
+ * @addtogroup hooks
+ * @{
+ */
+
+/**
+ * Alter the pattern for a user's real name prior to generation.
+ *
+ * @param string $pattern
+ *   The real name pattern string prior to token replacement.
+ * @param object $account
+ *   A user account object.
+ *
+ * @see realname_update()
+ *
+ * @ingroup realname
+ */
+function hook_realname_pattern_alter(&$pattern, $account) {
+
+}
+
+/**
+ * Alter a user's real name before it is saved to the database.
+ *
+ * @param string $realname
+ *   The user's generated real name.
+ * @param object $account
+ *   A user account object.
+ *
+ * @see realname_update()
+ *
+ * @ingroup realname
+ */
+function hook_realname_alter(&$realname, $account) {
+
+}
+
+/**
+ * Respond to updates to an account's real name.
+ *
+ * @see realname_update()
+ *
+ * @ingroup realname
+ */
+function hook_realname_update($realname, $account) {
+
+}
+
+/**
+ * @} End of "addtogroup hooks".
+ */
diff --git a/web/modules/realname/realname.info.yml b/web/modules/realname/realname.info.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e8546096737fbd46f51a457a0c328cd2154f39a1
--- /dev/null
+++ b/web/modules/realname/realname.info.yml
@@ -0,0 +1,13 @@
+name: 'Real name'
+type: module
+description: 'Provides token-based name displays for users.'
+configure: realname.admin_settings_form
+# core: 8.x
+dependencies:
+  - token:token
+
+# Information added by Drupal.org packaging script on 2019-01-31
+version: '8.x-1.0-rc2'
+core: '8.x'
+project: 'realname'
+datestamp: 1548970384
diff --git a/web/modules/realname/realname.install b/web/modules/realname/realname.install
new file mode 100644
index 0000000000000000000000000000000000000000..0fa66a5a669317b7d04dceb5755268187073bd58
--- /dev/null
+++ b/web/modules/realname/realname.install
@@ -0,0 +1,50 @@
+<?php
+
+/**
+ * @file
+ * Installation file for Realname module.
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function realname_schema() {
+  $schema['realname'] = [
+    'description' => 'Computed Real Names to reduce overhead.',
+    'fields' => [
+      'uid' => [
+        'description' => 'User ID, links to User table.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ],
+      'realname' => [
+        'description' => 'The generated real name of the user.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ],
+      'created' => [
+        'description' => 'The UNIX timestamp of when the real name was created.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ],
+    ],
+    'primary key' => ['uid'],
+    'indexes' => [
+      'realname' => ['realname'],
+    ],
+    'foreign keys' => [
+      'users' => [
+        'table' => 'users',
+        'columns' => ['uid' => 'uid'],
+      ],
+    ],
+  ];
+
+  return $schema;
+}
diff --git a/web/modules/realname/realname.links.menu.yml b/web/modules/realname/realname.links.menu.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6430d3793e547504cef5d5a7145982c776255a86
--- /dev/null
+++ b/web/modules/realname/realname.links.menu.yml
@@ -0,0 +1,5 @@
+realname.admin_settings_form:
+  title: 'Real name'
+  parent: user.admin_index
+  description: 'Use tokens to configure how user names are displayed.'
+  route_name: realname.admin_settings_form
diff --git a/web/modules/realname/realname.links.task.yml b/web/modules/realname/realname.links.task.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8e0d6cb649974710801cf9b35dcf160cca9d525a
--- /dev/null
+++ b/web/modules/realname/realname.links.task.yml
@@ -0,0 +1,4 @@
+realname.admin_settings_form_tab:
+  route_name: realname.admin_settings_form
+  title: 'Real name'
+  base_route: entity.user.admin_form
diff --git a/web/modules/realname/realname.module b/web/modules/realname/realname.module
new file mode 100644
index 0000000000000000000000000000000000000000..e4982f84cdaf0956d0eec3a00de52692cd32d6bf
--- /dev/null
+++ b/web/modules/realname/realname.module
@@ -0,0 +1,289 @@
+<?php
+
+/**
+ * @file
+ * Provides token-based name displays for users.
+ *
+ * @todo Add a 'view realname' permission enabled by default
+ * @todo Allow users to login with their real name
+ * @todo Disable the username field
+ */
+
+use Drupal\Component\Utility\Html;
+use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Link;
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Url;
+use Drupal\user\Entity\User;
+
+/**
+ * @defgroup realname Real name API
+ */
+
+/**
+ * Implements hook_help().
+ */
+function realname_help($route_name, RouteMatchInterface $route_match) {
+  switch ($route_name) {
+    // Main module help for the Realname module.
+    case 'realname.admin_settings_form':
+    case 'help.page.realname':
+      return '<p>' . t("A Real Name is what the site developer decides that users' names should look like. It is constructed from various tokens that are available within the site.") . '</p>';
+  }
+}
+
+/**
+ * Implements hook_entity_extra_field_info().
+ */
+function realname_entity_extra_field_info() {
+  $fields['user']['user']['display']['realname'] = [
+    'label' => t('Real name'),
+    'description' => t('Real name'),
+    'weight' => -1,
+    'visible' => FALSE,
+  ];
+
+  return $fields;
+}
+
+/**
+ * Implements hook_user_format_name_alter().
+ */
+function realname_user_format_name_alter(&$name, $account) {
+  static $in_username_alter = FALSE;
+  $uid = $account->id();
+
+  // Don't alter anonymous users or objects that do not have any user ID.
+  if (empty($uid)) {
+    return;
+  }
+
+  // Real name was loaded/generated via hook_user_load(), so re-use it.
+  if (isset($account->realname)) {
+    if (Unicode::strlen($account->realname)) {
+      // Only if the real name is a non-empty string is $name actually altered.
+      $name = $account->realname;
+    }
+    return;
+  }
+
+  // Real name was not yet available for the account so we need to generate it.
+  // Because tokens may call format_username() we need to prevent recursion.
+  if (!$in_username_alter) {
+    $in_username_alter = TRUE;
+
+    // If $account->realname was undefined, then the user account object was
+    // not properly loaded. We must enforce calling user_load().
+    if ($realname_account = User::load($uid)) {
+      realname_user_format_name_alter($name, $realname_account);
+    }
+
+    $in_username_alter = FALSE;
+  }
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_load().
+ */
+function realname_user_load(array $accounts) {
+  $realnames = realname_load_multiple($accounts);
+  foreach ($realnames as $uid => $realname) {
+    $accounts[$uid]->realname = $realname;
+  }
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_update().
+ */
+function realname_user_update(EntityInterface $account) {
+  // Since user data may have changed, update the realname and its cache.
+  $realnames = &drupal_static('realname_load_multiple', []);
+  $realnames[$account->id()] = realname_update($account);
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_delete().
+ */
+function realname_user_delete(EntityInterface $account) {
+  realname_delete($account->id());
+}
+
+/**
+ * Implements hook_ENTITY_TYPE_view() for user entities.
+ */
+function realname_user_view(array &$build, EntityInterface $account, EntityViewDisplayInterface $display, $view_mode) {
+  if ($display->getComponent('realname')) {
+    if ($account->access('view')) {
+      $url = Url::fromRoute('entity.user.canonical', ['user' => $account->id()]);
+      $markup = Link::fromTextAndUrl($account->realname, $url)->toString();
+    }
+    else {
+      $markup = Html::escape($account->realname);
+    }
+
+    $build['realname'] = [
+      '#theme' => 'field',
+      '#title' => t('Real name'),
+      '#label_display' => 'inline',
+      '#view_mode' => '_custom',
+      '#field_name' => 'realname',
+      '#field_type' => 'text',
+      '#field_translatable' => FALSE,
+      '#entity_type' => 'custom',
+      '#bundle' => 'custom',
+      '#object' => $account,
+      '#items' => [TRUE],
+      '#is_multiple' => FALSE,
+      0 => [
+        '#markup' => $markup,
+      ],
+    ];
+  }
+}
+
+/**
+ * @addtogroup realname
+ * @{
+ */
+
+/**
+ * Loads a real name.
+ *
+ * @param Drupal\user\Entity\User $account
+ *   A user account object.
+ *
+ * @return mixed
+ *   The user's generated real name.
+ */
+function realname_load(User $account) {
+  $realnames = realname_load_multiple([$account->id() => $account]);
+  return reset($realnames);
+}
+
+/**
+ * Loads multiple real names.
+ *
+ * @param array $accounts
+ *   An array of user account objects keyed by user ID.
+ *
+ * @return array
+ *   An array of real names keyed by user ID.
+ */
+function realname_load_multiple(array $accounts) {
+  $realnames = &drupal_static(__FUNCTION__, []);
+
+  if ($new_accounts = array_diff_key($accounts, $realnames)) {
+    // Attempt to fetch realnames from the database first.
+    $realnames += \Drupal::database()->query("SELECT uid, realname FROM {realname} WHERE uid IN (:uids[])", [':uids[]' => array_keys($new_accounts)])->fetchAllKeyed();
+
+    // For each account that was not present in the database, generate its
+    // real name.
+    foreach ($new_accounts as $uid => $account) {
+      if (!isset($realnames[$uid])) {
+        $realnames[$uid] = realname_update($account);
+      }
+    }
+  }
+
+  return array_intersect_key($realnames, $accounts);
+}
+
+/**
+ * Update the realname for a user account.
+ *
+ * @param Drupal\user\Entity\User $account
+ *   A user account object.
+ *
+ * @return string
+ *   A string with the real name.
+ *
+ * @see hook_realname_pattern_alter()
+ * @see hook_realname_alter()
+ * @see hook_realname_update()
+ */
+function realname_update(User $account) {
+  $realname = '';
+
+  if (!$account->isAnonymous()) {
+    // Get the default pattern and allow other modules to alter it.
+    $config = \Drupal::config('realname.settings');
+    $pattern = $config->get('pattern');
+    \Drupal::moduleHandler()->alter('realname_pattern', $pattern, $account);
+
+    // Perform token replacement on the real name pattern.
+    $realname = \Drupal::token()->replace($pattern, ['user' => $account], ['clear' => TRUE, 'sanitize' => FALSE]);
+
+    // Remove any HTML tags.
+    $realname = strip_tags(Html::decodeEntities($realname));
+
+    // Remove double spaces (if a token had no value).
+    $realname = preg_replace('/ {2,}/', ' ', $realname);
+
+    // Allow other modules to alter the generated realname.
+    \Drupal::moduleHandler()->alter('realname', $realname, $account);
+
+    // The name must be trimmed to 255 characters before inserting into the
+    // database.
+    $realname = Unicode::truncate(trim($realname), 255);
+  }
+  else {
+    // DisplayName cannot generated with tokens for anonymous users.
+    $realname = $account->label();
+  }
+
+  // Save to the database and the static cache.
+  \Drupal::database()->merge('realname')
+    ->key(['uid' => $account->id()])
+    ->fields([
+      'realname' => $realname,
+      'created' => \Drupal::time()->getRequestTime(),
+    ])
+    ->execute();
+
+  // Allow modules to react to the realname being updated.
+  \Drupal::moduleHandler()->invokeAll('realname_update', [$realname, $account]);
+
+  // Clear the entity cache.
+  /** @var \Drupal\user\UserStorageInterface $user_storage */
+  $user_storage = \Drupal::getContainer()->get('entity.manager')->getStorage('user');
+  $user_storage->resetCache([$account->id()]);
+
+  return $realname;
+}
+
+/**
+ * Delete a real name.
+ *
+ * @param int $uid
+ *   A user ID.
+ */
+function realname_delete($uid) {
+  return realname_delete_multiple([$uid]);
+}
+
+/**
+ * Delete multiple real names.
+ *
+ * @param array $uids
+ *   An array of user IDs.
+ */
+function realname_delete_multiple(array $uids) {
+  \Drupal::database()->delete('realname')->condition('uid', $uids, 'IN')->execute();
+  drupal_static_reset('realname_load_multiple');
+  \Drupal::entityTypeManager()->getStorage('user')->resetCache($uids);
+}
+
+/**
+ * Delete all real names.
+ */
+function realname_delete_all() {
+  \Drupal::database()->truncate('realname')->execute();
+  drupal_static_reset('realname_load_multiple');
+  \Drupal::entityTypeManager()->getStorage('user')->resetCache();
+}
+
+/**
+ * @} End of "addtogroup realname".
+ */
diff --git a/web/modules/realname/realname.permissions.yml b/web/modules/realname/realname.permissions.yml
new file mode 100644
index 0000000000000000000000000000000000000000..6d93be6c8e757e7957ec29dd2c95540ec2fd73b9
--- /dev/null
+++ b/web/modules/realname/realname.permissions.yml
@@ -0,0 +1,3 @@
+administer realname:
+  title: 'Administer Real Name'
+  description: 'Allows users to administer realname settings.'
diff --git a/web/modules/realname/realname.routing.yml b/web/modules/realname/realname.routing.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c65b1e64689a0c00118836cd324cf7a4a3200d18
--- /dev/null
+++ b/web/modules/realname/realname.routing.yml
@@ -0,0 +1,7 @@
+realname.admin_settings_form:
+  path: '/admin/config/people/realname'
+  defaults:
+    _form: 'Drupal\realname\Form\RealnameAdminSettingsForm'
+    _title: 'Real name'
+  requirements:
+    _permission: 'administer realname'
diff --git a/web/modules/realname/realname.services.yml b/web/modules/realname/realname.services.yml
new file mode 100644
index 0000000000000000000000000000000000000000..cf4fe9bb1310e3882bbced712ac26738e1a53b81
--- /dev/null
+++ b/web/modules/realname/realname.services.yml
@@ -0,0 +1,11 @@
+services:
+  realname.config_cache_tag:
+    class: Drupal\realname\EventSubscriber\ConfigCacheTag
+    arguments: ['@cache_tags.invalidator']
+    tags:
+      - { name: event_subscriber }
+
+  realname.route.subscriber:
+    class: Drupal\realname\Routing\RealnameRouteSubscriber
+    tags:
+      - { name: event_subscriber }
diff --git a/web/modules/realname/realname.views.inc b/web/modules/realname/realname.views.inc
new file mode 100644
index 0000000000000000000000000000000000000000..a4af06a930ecee3fe5c9df3d67a9d8e2881c3c1b
--- /dev/null
+++ b/web/modules/realname/realname.views.inc
@@ -0,0 +1,41 @@
+<?php
+
+/**
+ * @file
+ * Views integration for the realname module.
+ */
+
+/**
+ * Implements hook_views_data().
+ */
+function realname_views_data() {
+  $data['realname']['table']['group'] = t('Realname');
+  $data['realname']['table']['join'] = [
+    'users' => [
+      'left_field' => 'uid',
+      'field' => 'uid',
+    ],
+  ];
+
+  $data['realname']['realname'] = [
+    'title' => t('Real name'),
+    'help' => t("The user's real name."),
+    'field' => [
+      'handler' => 'views_handler_field_user',
+      'click sortable' => TRUE,
+    ],
+    'sort' => [
+      'handler' => 'views_handler_sort',
+    ],
+    'argument' => [
+      'handler' => 'views_handler_argument_string',
+    ],
+    'filter' => [
+      'handler' => 'views_handler_filter_string',
+      'title' => t('Name'),
+      'help' => t("The user's real name. This filter does not check if the user exists and allows partial matching. Does not utilize autocomplete."),
+    ],
+  ];
+
+  return $data;
+}
diff --git a/web/modules/realname/src/Controller/RealnameAutocompleteController.php b/web/modules/realname/src/Controller/RealnameAutocompleteController.php
new file mode 100644
index 0000000000000000000000000000000000000000..fd536d53d539f6b56987da971aa7344d379827f7
--- /dev/null
+++ b/web/modules/realname/src/Controller/RealnameAutocompleteController.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace Drupal\realname\Controller;
+
+use Drupal\system\Controller\EntityAutocompleteController;
+use Drupal\Component\Utility\Crypt;
+use Drupal\Component\Utility\Tags;
+use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Database\Query\Condition;
+use Drupal\Core\Site\Settings;
+use Drupal\user\Entity\User;
+use Symfony\Component\HttpFoundation\JsonResponse;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+
+/**
+ * Defines a route controller for entity autocomplete form elements.
+ */
+class RealnameAutocompleteController extends EntityAutocompleteController {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function handleAutocomplete(Request $request, $target_type, $selection_handler, $selection_settings_key) {
+    if ($target_type != 'user') {
+      return parent::handleAutocomplete($request, $target_type, $selection_handler, $selection_settings_key);
+    }
+
+    $matches = [];
+    if ($input = $request->query->get('q')) {
+      $typed_string = Tags::explode($input);
+      $typed_string = Unicode::strtolower(array_pop($typed_string));
+      $selection_settings = $this->keyValue->get($selection_settings_key, FALSE);
+      if ($selection_settings !== FALSE) {
+        $selection_settings_hash = Crypt::hmacBase64(serialize($selection_settings) . $target_type . $selection_handler, Settings::getHashSalt());
+        if ($selection_settings_hash !== $selection_settings_key) {
+          throw new AccessDeniedHttpException('Invalid selection settings key.');
+        }
+      }
+      else {
+        throw new AccessDeniedHttpException();
+      }
+
+      $matches = $this->getMatches($selection_settings, $typed_string);
+    }
+
+    return new JsonResponse($matches);
+  }
+
+  /**
+   * Gets matched labels based on a given search string.
+   *
+   * @param array $selection_settings
+   *   An array of settings that will be passed to the selection handler.
+   * @param string $string
+   *   (optional) The label of the entity to query by.
+   *
+   * @return array
+   *   An array of matched entity labels, in the format required by the AJAX
+   *   autocomplete API (e.g. array('value' => $value, 'label' => $label)).
+   *
+   * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
+   *   Thrown when the current user doesn't have access to the specified entity.
+   */
+  protected function getMatches($selection_settings, $string = '') {
+    $matches = [];
+
+    if (isset($string)) {
+      // Get an array of matching entities.
+      $match_operator = !empty($selection_settings['match_operator']) ? $selection_settings['match_operator'] : 'CONTAINS';
+      $include_anonymous = isset($selection_settings['include_anonymous']) ? $selection_settings['include_anonymous'] : TRUE;
+
+      $connection = \Drupal::database();
+      $query = $connection->select('users_field_data', 'u');
+      $query->fields('u', ['uid']);
+      $query->leftJoin('realname', 'rn', 'u.uid = rn.uid');
+      if ($match_operator == 'CONTAINS') {
+        $query->condition((new Condition('OR'))
+          ->condition('rn.realname', '%' . $connection->escapeLike($string) . '%', 'LIKE')
+          ->condition('u.name', '%' . $connection->escapeLike($string) . '%', 'LIKE')
+        );
+      }
+      else {
+        $query->condition((new Condition('OR'))
+          ->condition('rn.realname', $connection->escapeLike($string) . '%', 'LIKE')
+          ->condition('u.name', $connection->escapeLike($string) . '%', 'LIKE')
+        );
+      }
+      if ($include_anonymous == FALSE) {
+        $query->condition('u.uid', 0, '>');
+      }
+      $query->range(0, 10);
+      $uids = $query->execute()->fetchCol();
+      $accounts = User::loadMultiple($uids);
+
+      /* @var $account User */
+      foreach ($accounts as $account) {
+        $matches[] = [
+          'value' => t('@realname (@id)', ['@realname' => $account->getDisplayName(), '@id' => $account->id()]),
+          'label' => t('@realname (@username)', ['@realname' => $account->getDisplayName(), '@username' => $account->getAccountName()]),
+        ];
+      }
+    }
+    return $matches;
+  }
+
+}
diff --git a/web/modules/realname/src/EventSubscriber/ConfigCacheTag.php b/web/modules/realname/src/EventSubscriber/ConfigCacheTag.php
new file mode 100644
index 0000000000000000000000000000000000000000..a3144fcdb9adc2970c52842c3df7ece4f63aa211
--- /dev/null
+++ b/web/modules/realname/src/EventSubscriber/ConfigCacheTag.php
@@ -0,0 +1,58 @@
+<?php
+
+namespace Drupal\realname\EventSubscriber;
+
+use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
+use Drupal\Core\Config\ConfigCrudEvent;
+use Drupal\Core\Config\ConfigEvents;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * A subscriber invalidating cache tags when realname config objects are saved.
+ */
+class ConfigCacheTag implements EventSubscriberInterface {
+
+  /**
+   * The cache tags invalidator.
+   *
+   * @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface
+   */
+  protected $cacheTagsInvalidator;
+
+  /**
+   * Constructs a RealnameCacheTag object.
+   *
+   * @param \Drupal\Core\Cache\CacheTagsInvalidatorInterface $cache_tags_invalidator
+   *   The cache tags invalidator.
+   */
+  public function __construct(CacheTagsInvalidatorInterface $cache_tags_invalidator) {
+    $this->cacheTagsInvalidator = $cache_tags_invalidator;
+  }
+
+  /**
+   * Invalidate cache tags when particular realname config objects are saved.
+   *
+   * @param \Drupal\Core\Config\ConfigCrudEvent $event
+   *   The Event to process.
+   */
+  public function onSave(ConfigCrudEvent $event) {
+    // Check if realname settings object has been changed.
+    if ($event->getConfig()->getName() === 'realname.settings') {
+      // Clear the realname cache if the pattern was changed.
+      realname_delete_all();
+
+      // A change to the display-name pattern must invalidate the render cache
+      // since the display-name could be used anywhere.
+      $this->cacheTagsInvalidator->invalidateTags(['rendered']);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function getSubscribedEvents() {
+    $events[ConfigEvents::SAVE][] = ['onSave'];
+    return $events;
+  }
+
+}
diff --git a/web/modules/realname/src/Form/RealnameAdminSettingsForm.php b/web/modules/realname/src/Form/RealnameAdminSettingsForm.php
new file mode 100644
index 0000000000000000000000000000000000000000..d8c9a7e9d982bad0f8d94b50b17ca0d845ef26a0
--- /dev/null
+++ b/web/modules/realname/src/Form/RealnameAdminSettingsForm.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace Drupal\realname\Form;
+
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Form\FormStateInterface;
+
+/**
+ * Configure Realname settings for this site.
+ */
+class RealnameAdminSettingsForm extends ConfigFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'realname_admin_settings';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getEditableConfigNames() {
+    return ['realname.settings'];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $config = $this->config('realname.settings');
+
+    $form['general'] = [
+      '#type' => 'fieldset',
+      '#title' => $this->t('General settings'),
+    ];
+
+    $note = '<div>';
+    $note .= $this->t('Note that if it is changed, all current Realnames will be deleted and the list in the database will be rebuilt as needed.');
+    $note .= '</div>';
+
+    $form['general']['realname_pattern'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Realname pattern'),
+      '#default_value' => $config->get('pattern'),
+      '#element_validate' => ['token_element_validate'],
+      '#token_types' => ['user'],
+      '#min_tokens' => 1,
+      '#required' => TRUE,
+      '#maxlength' => 256,
+      '#description' => $this->t('This pattern will be used to construct Realnames for all users.') . $note,
+    ];
+    // Add the token tree UI.
+    $form['general']['token_help'] = [
+      '#theme' => 'token_tree_link',
+      '#token_types' => ['user'],
+      '#global_types' => FALSE,
+    ];
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    parent::validateForm($form, $form_state);
+
+    $pattern = $form_state->getValue('realname_pattern');
+
+    // Tokens that will cause recursion.
+    $tokens = [
+      '[user:name]',
+    ];
+    foreach ($tokens as $token) {
+      if (strpos($pattern, $token) !== FALSE) {
+        $form_state->setErrorByName('realname_pattern', $this->t('The %token token cannot be used as it will cause recursion.', ['%token' => $token]));
+      }
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $config = $this->config('realname.settings');
+
+    if ($form['general']['realname_pattern']['#default_value'] != $form_state->getValue('realname_pattern')) {
+      $config->set('pattern', $form_state->getValue('realname_pattern'))->save();
+    }
+
+    parent::submitForm($form, $form_state);
+  }
+
+}
diff --git a/web/modules/realname/src/Plugin/Action/RealnameUpdateRealname.php b/web/modules/realname/src/Plugin/Action/RealnameUpdateRealname.php
new file mode 100644
index 0000000000000000000000000000000000000000..ec0d7e2716bbf84f7e32b3fae9fd00cc99585096
--- /dev/null
+++ b/web/modules/realname/src/Plugin/Action/RealnameUpdateRealname.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace Drupal\realname\Plugin\Action;
+
+use Drupal\Core\Action\ActionBase;
+use Drupal\Core\Session\AccountInterface;
+
+/**
+ * Update user real name.
+ *
+ * @Action(
+ *   id = "realname_update_realname_action",
+ *   label = @Translation("Update real name"),
+ *   type = "user"
+ * )
+ */
+class RealnameUpdateRealname extends ActionBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function execute($account = NULL) {
+    realname_update($account);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
+    /** @var \Drupal\user\UserInterface $object */
+    $access = $object->status->access('edit', $account, TRUE)
+      ->andIf($object->access('update', $account, TRUE));
+
+    return $return_as_object ? $access : $access->isAllowed();
+  }
+
+}
diff --git a/web/modules/realname/src/Plugin/migrate/process/RealnameReplaceToken.php b/web/modules/realname/src/Plugin/migrate/process/RealnameReplaceToken.php
new file mode 100644
index 0000000000000000000000000000000000000000..f800f1dab05659e5192da61a62d11ac4850f9334
--- /dev/null
+++ b/web/modules/realname/src/Plugin/migrate/process/RealnameReplaceToken.php
@@ -0,0 +1,33 @@
+<?php
+
+namespace Drupal\realname\Plugin\migrate\process;
+
+use Drupal\migrate\ProcessPluginBase;
+use Drupal\migrate\MigrateExecutableInterface;
+use Drupal\migrate\Row;
+
+/**
+ * If the source evaluates to empty, we skip the current row.
+ *
+ * @MigrateProcessPlugin(
+ *   id = "realname_replace_token",
+ *   handle_multiples = TRUE
+ * )
+ */
+class RealnameReplaceToken extends ProcessPluginBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) {
+    list($realname_pattern) = $value;
+
+    // Previous D7 realname token need to be replaced by D8 core token.
+    //
+    // At least two tokens may exists:
+    // - [user:name-raw]
+    // - [current-user:name-raw]
+    return str_ireplace(':name-raw]', ':account-name]', $realname_pattern);
+  }
+
+}
diff --git a/web/modules/realname/src/Routing/RealnameRouteSubscriber.php b/web/modules/realname/src/Routing/RealnameRouteSubscriber.php
new file mode 100644
index 0000000000000000000000000000000000000000..fe927de956c7930e1a682480528014d347751f34
--- /dev/null
+++ b/web/modules/realname/src/Routing/RealnameRouteSubscriber.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Drupal\realname\Routing;
+
+use Drupal\Core\Routing\RouteSubscriberBase;
+use Symfony\Component\Routing\RouteCollection;
+
+/**
+ * Subscriber for routes.
+ */
+class RealnameRouteSubscriber extends RouteSubscriberBase {
+  /**
+   * {@inheritdoc}
+   */
+  protected function alterRoutes(RouteCollection $collection) {
+    if ($route = $collection->get('system.entity_autocomplete')) {
+      $route->setDefault('_controller', '\Drupal\realname\Controller\RealnameAutocompleteController::handleAutocomplete');
+    }
+  }
+}
diff --git a/web/modules/realname/src/Tests/RealnameBasicTest.php b/web/modules/realname/src/Tests/RealnameBasicTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7a0400c4af57f591c2f8e7fb8fa40ea306e2f1b5
--- /dev/null
+++ b/web/modules/realname/src/Tests/RealnameBasicTest.php
@@ -0,0 +1,150 @@
+<?php
+
+namespace Drupal\realname\Tests;
+
+use Drupal\simpletest\WebTestBase;
+use Drupal\user\Entity\User;
+
+/**
+ * Test basic functionality of Realname module.
+ *
+ * @group Realname
+ */
+class RealnameBasicTest extends WebTestBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = [
+    'realname',
+    'field_ui',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $permissions = [
+      'access administration pages',
+      'administer modules',
+      'administer realname',
+      'administer site configuration',
+      'administer user fields',
+      'administer user form display',
+      'administer user display',
+      'administer users',
+    ];
+
+    // User to set up realname.
+    $this->admin_user = $this->drupalCreateUser($permissions);
+    $this->drupalLogin($this->admin_user);
+  }
+
+  /**
+   * Test realname configuration.
+   */
+  public function testRealnameConfiguration() {
+    // Check if Configure link is available on 'Modules' page.
+    // Requires 'administer modules' permission.
+    $this->drupalGet('admin/modules');
+    $this->assertRaw('admin/config/people/realname', '[testRealnameConfiguration]: Configure link from Modules page to Realname settings page exists.');
+
+    // Check for setting page's presence.
+    $this->drupalGet('admin/config/people/realname');
+    $this->assertRaw(t('Realname pattern'), '[testRealnameConfiguration]: Settings page displayed.');
+
+    // Save form with allowed token.
+    $edit['realname_pattern'] = '[user:account-name]';
+    $this->drupalPostForm('admin/config/people/realname', $edit, t('Save configuration'));
+    $this->assertRaw(t('The configuration options have been saved.'), '[testRealnameConfiguration]: Settings form has been saved.');
+
+    // Check token recursion protection.
+    $edit['realname_pattern'] = '[user:name]';
+    $this->drupalPostForm('admin/config/people/realname', $edit, t('Save configuration'));
+    $this->assertRaw(t('The %token token cannot be used as it will cause recursion.', ['%token' => '[user:name]']), '[testRealnameConfiguration]: Invalid token found.');
+  }
+
+  /**
+   * Test realname alter functions.
+   */
+  public function testRealnameUsernameAlter() {
+    // Add a test string and see if core username has been replaced by realname.
+    $edit['realname_pattern'] = '[user:account-name] (UID: [user:uid])';
+    $this->drupalPostForm('admin/config/people/realname', $edit, t('Save configuration'));
+
+    $this->drupalGet('user/' . $this->admin_user->id());
+    // @ @FIXME: Needs patch https://www.drupal.org/node/2629286
+    // $this->assertRaw($this->admin_user->getDisplayName(), '[testRealnameUsernameAlter]: Real name shown on user page.');
+
+    $this->drupalGet('user/' . $this->admin_user->id() . '/edit');
+    // @FIXME: Needs patch https://www.drupal.org/node/2629286
+    // $this->assertRaw($this->admin_user->getDisplayName(), '[testRealnameUsernameAlter]: Real name shown on user edit page.');
+
+    /** @var \Drupal\user\entity\User $user_account */
+    $user_account = $this->admin_user;
+    $username_before = $user_account->getAccountName();
+    $user_account->save();
+    $username_after = $user_account->getAccountName();
+    $this->assertEqual($username_before, $username_after, 'Username did not change after save');
+  }
+
+  /**
+   * Test realname display configuration.
+   */
+  public function testRealnameManageDisplay() {
+    $edit['realname_pattern'] = '[user:account-name]';
+    $this->drupalPostForm('admin/config/people/realname', $edit, t('Save configuration'));
+
+    $this->drupalGet('admin/config/people/accounts/fields');
+    $this->assertTitle('Manage fields | Drupal');
+    $this->assertNoRaw('Real name', '[testRealnameManageDisplay]: Real name field not shown in manage fields list.');
+
+    $this->drupalGet('admin/config/people/accounts/form-display');
+    $this->assertTitle('Manage form display | Drupal');
+    $this->assertNoRaw('Real name', '[testRealnameManageDisplay]: Real name field not shown in manage form display list.');
+
+    $this->drupalGet('admin/config/people/accounts/display');
+    $this->assertTitle('Manage display | Drupal');
+    $this->assertRaw('Real name', '[testRealnameManageDisplay]: Real name field shown in manage display.');
+
+    // By default the realname field is not visible.
+    $this->drupalGet('user/' . $this->admin_user->id());
+    $this->assertNoText('Real name', '[testRealnameManageDisplay]: Real name field not visible on user page.');
+
+    // Make realname field visible on user page.
+    $this->drupalGet('admin/config/people/accounts/display');
+    $edit = ['fields[realname][region]' => 'content'];
+    $this->drupalPostForm(NULL, $edit, t('Save'));
+    $this->assertResponse(200);
+
+    $this->drupalGet('user/' . $this->admin_user->id());
+    $this->assertText('Real name', '[testRealnameManageDisplay]: Real name field visible on user page.');
+  }
+
+  /**
+   * Test realname user update.
+   */
+  public function testRealnameUserUpdate() {
+    $edit['realname_pattern'] = '[user:account-name]';
+    $this->drupalPostForm('admin/config/people/realname', $edit, t('Save configuration'));
+
+    $user1 = User::load($this->admin_user->id());
+    $realname1 = $user1->realname;
+
+    // Update user name.
+    $user1->name = $this->randomMachineName();
+    $user1->save();
+
+    // Reload the user.
+    $user2 = User::load($this->admin_user->id());
+    $realname2 = $user2->realname;
+
+    // Check if realname changed.
+    $this->assertTrue($realname1);
+    $this->assertTrue($realname2);
+    $this->assertNotEqual($realname1, $realname2, '[testRealnameUserUpdate]: Real name changed.');
+  }
+
+}
diff --git a/web/themes/asc_bootstrap/assets/sass/components/_wysiwyg.scss b/web/themes/asc_bootstrap/assets/sass/components/_wysiwyg.scss
index 2c4c23c00fc01de030e7a1f240f160f401f45593..36441029c8195e1d622aec22d12c83b1ce44325a 100644
--- a/web/themes/asc_bootstrap/assets/sass/components/_wysiwyg.scss
+++ b/web/themes/asc_bootstrap/assets/sass/components/_wysiwyg.scss
@@ -29,9 +29,12 @@
 
 .align-center {
   .field--name-field-media-image {
-    padding: 15px;
-    margin: 0 auto;
+    padding: 15px 0;
     width: auto;
+
+    img {
+      margin: 0 auto;
+    }
   }
 
   figcaption {
diff --git a/web/themes/asc_bootstrap/assets/sass/layout/_default.scss b/web/themes/asc_bootstrap/assets/sass/layout/_default.scss
index 1cb3f08c42dfc9bcc0991d43a065879de6f8fbdb..8687e31ad2695d3b17cc2788b9698b6de7cdaa2d 100755
--- a/web/themes/asc_bootstrap/assets/sass/layout/_default.scss
+++ b/web/themes/asc_bootstrap/assets/sass/layout/_default.scss
@@ -221,29 +221,6 @@ h5, h6 {
 }
 
 
-// --------------------------------------------------
-
-//## WYSIWYG.
-
-.field--name-field-media-image {
-	padding-bottom: 15px;
-}
-
-.align-left {
-
-	.field--name-field-media-image {
-		padding: 0 15px 0 0;
-	}
-}
-
-.align-right {
-
-	.field--name-field-media-image {
-		padding: 0 0 0 15px;
-	}
-}
-
-
 // --------------------------------------------------
 
 //## Out-of-box contact form.
diff --git a/web/themes/asc_bootstrap/assets/sass/pages/_landing-page.scss b/web/themes/asc_bootstrap/assets/sass/pages/_landing-page.scss
index 184e6cec958af88869a949b4bbec82687686c663..6c722167c7edecc483e806e6a9d097989e1f6825 100644
--- a/web/themes/asc_bootstrap/assets/sass/pages/_landing-page.scss
+++ b/web/themes/asc_bootstrap/assets/sass/pages/_landing-page.scss
@@ -110,17 +110,38 @@
 
 .call-out-container {
 
-  .field--name-field-image-link {
-    a {
-      color: $black-base;
-      font-size: 20px;
-      padding-top: 5px;
-      font-weight: 600;
+  .img-link-wrapper:hover + .field--type-link a {
+    color: $brand-red;
+    text-decoration: none;
+  }
 
-      &:hover {
-        color: $brand-red;
-        text-decoration: underline;
-      }
+  .field--item:hover > a {
+    color: $brand-red;
+    text-decoration: none;
+  }
+
+  a {
+    color: $black-base;
+    font-size: 20px;
+    padding-top: 5px;
+    font-weight: 600;
+
+    &:hover {
+      color: $brand-red;
+      text-decoration: none;
+    }
+  }
+
+  .field--type-link {
+    position: absolute;
+    bottom: 0;
+    margin-bottom: 15px;
+    width: 100%;
+
+    .field--item {
+      padding: 15px;
+      margin-right: 30px;
+      background: rgba(255,255,255,0.7);
     }
   }
 }
@@ -136,10 +157,10 @@
   .call-out-container {
 
     a {
-      color: $white;
+      text-decoration: none;
 
       &:hover {
-        color: $white;
+        text-decoration: none;
       }
     }
   }
diff --git a/web/themes/asc_bootstrap/css/style.css b/web/themes/asc_bootstrap/css/style.css
index dacf49422e2d2c3d02f8351dceef3bc188c46a31..1e7bdb4ae6a62af0767090c6432ad6705275c91d 100644
--- a/web/themes/asc_bootstrap/css/style.css
+++ b/web/themes/asc_bootstrap/css/style.css
@@ -9095,31 +9095,16 @@ h5, h6 {
 }
 
 /* line 228, ../assets/sass/layout/_default.scss */
-.field--name-field-media-image {
-  padding-bottom: 15px;
-}
-
-/* line 234, ../assets/sass/layout/_default.scss */
-.align-left .field--name-field-media-image {
-  padding: 0 15px 0 0;
-}
-
-/* line 241, ../assets/sass/layout/_default.scss */
-.align-right .field--name-field-media-image {
-  padding: 0 0 0 15px;
-}
-
-/* line 251, ../assets/sass/layout/_default.scss */
 #contact-message-feedback-form {
   margin-bottom: 20px;
 }
 
-/* line 260, ../assets/sass/layout/_default.scss */
+/* line 237, ../assets/sass/layout/_default.scss */
 .user-login-form {
   margin-bottom: 40px;
 }
 
-/* line 264, ../assets/sass/layout/_default.scss */
+/* line 241, ../assets/sass/layout/_default.scss */
 #user-form {
   margin-bottom: 40px;
 }
@@ -11797,11 +11782,14 @@ textarea.form-control {
 
 /* line 31, ../assets/sass/components/_wysiwyg.scss */
 .align-center .field--name-field-media-image {
-  padding: 15px;
-  margin: 0 auto;
+  padding: 15px 0;
   width: auto;
 }
-/* line 37, ../assets/sass/components/_wysiwyg.scss */
+/* line 35, ../assets/sass/components/_wysiwyg.scss */
+.align-center .field--name-field-media-image img {
+  margin: 0 auto;
+}
+/* line 40, ../assets/sass/components/_wysiwyg.scss */
 .align-center figcaption {
   text-align: center;
 }
@@ -11923,20 +11911,43 @@ article.page {
   float: right;
 }
 
-/* line 114, ../assets/sass/pages/_landing-page.scss */
-.call-out-container .field--name-field-image-link a {
+/* line 113, ../assets/sass/pages/_landing-page.scss */
+.call-out-container .img-link-wrapper:hover + .field--type-link a {
+  color: #BB0000;
+  text-decoration: none;
+}
+/* line 118, ../assets/sass/pages/_landing-page.scss */
+.call-out-container .field--item:hover > a {
+  color: #BB0000;
+  text-decoration: none;
+}
+/* line 123, ../assets/sass/pages/_landing-page.scss */
+.call-out-container a {
   color: #000000;
   font-size: 20px;
   padding-top: 5px;
   font-weight: 600;
 }
-/* line 120, ../assets/sass/pages/_landing-page.scss */
-.call-out-container .field--name-field-image-link a:hover {
+/* line 129, ../assets/sass/pages/_landing-page.scss */
+.call-out-container a:hover {
   color: #BB0000;
-  text-decoration: underline;
+  text-decoration: none;
+}
+/* line 135, ../assets/sass/pages/_landing-page.scss */
+.call-out-container .field--type-link {
+  position: absolute;
+  bottom: 0;
+  margin-bottom: 15px;
+  width: 100%;
+}
+/* line 141, ../assets/sass/pages/_landing-page.scss */
+.call-out-container .field--type-link .field--item {
+  padding: 15px;
+  margin-right: 30px;
+  background: rgba(255, 255, 255, 0.7);
 }
 
-/* line 138, ../assets/sass/pages/_landing-page.scss */
+/* line 159, ../assets/sass/pages/_landing-page.scss */
 .dgray-bg .call-out-container a,
 .dscarlet-bg .call-out-container a,
 .dviolet-bg .call-out-container a,
@@ -11944,9 +11955,9 @@ article.page {
 .dpurple-bg .call-out-container a,
 .dgreen-bg .call-out-container a,
 .dorange-bg .call-out-container a {
-  color: #ffffff;
+  text-decoration: none;
 }
-/* line 141, ../assets/sass/pages/_landing-page.scss */
+/* line 162, ../assets/sass/pages/_landing-page.scss */
 .dgray-bg .call-out-container a:hover,
 .dscarlet-bg .call-out-container a:hover,
 .dviolet-bg .call-out-container a:hover,
@@ -11954,10 +11965,10 @@ article.page {
 .dpurple-bg .call-out-container a:hover,
 .dgreen-bg .call-out-container a:hover,
 .dorange-bg .call-out-container a:hover {
-  color: #ffffff;
+  text-decoration: none;
 }
 
-/* line 150, ../assets/sass/pages/_landing-page.scss */
+/* line 171, ../assets/sass/pages/_landing-page.scss */
 .page-node-type-landing-page #half-t-left {
   position: absolute;
   z-index: 2;
@@ -11968,12 +11979,12 @@ article.page {
   border-right: 20px solid transparent;
 }
 @media (max-width: 768px) {
-  /* line 150, ../assets/sass/pages/_landing-page.scss */
+  /* line 171, ../assets/sass/pages/_landing-page.scss */
   .page-node-type-landing-page #half-t-left {
     bottom: -2px;
   }
 }
-/* line 163, ../assets/sass/pages/_landing-page.scss */
+/* line 184, ../assets/sass/pages/_landing-page.scss */
 .page-node-type-landing-page #half-t-right {
   position: absolute;
   z-index: 2;
@@ -11985,18 +11996,18 @@ article.page {
   border-left: 20px solid transparent;
 }
 @media (max-width: 768px) {
-  /* line 163, ../assets/sass/pages/_landing-page.scss */
+  /* line 184, ../assets/sass/pages/_landing-page.scss */
   .page-node-type-landing-page #half-t-right {
     bottom: -2px;
   }
 }
 
-/* line 185, ../assets/sass/pages/_landing-page.scss */
+/* line 206, ../assets/sass/pages/_landing-page.scss */
 .block-wrapper .region:nth-child(odd) {
   background: #F5F5F5;
 }
 
-/* line 191, ../assets/sass/pages/_landing-page.scss */
+/* line 212, ../assets/sass/pages/_landing-page.scss */
 .view-display-id-block_1 .view-header {
   text-transform: uppercase;
   float: left;
@@ -12005,48 +12016,48 @@ article.page {
   padding-bottom: 0;
   border-bottom: 1px solid #979797;
 }
-/* line 199, ../assets/sass/pages/_landing-page.scss */
+/* line 220, ../assets/sass/pages/_landing-page.scss */
 .view-display-id-block_1 .view-header .txt-re-news {
   text-align: left;
   padding: 0;
 }
-/* line 203, ../assets/sass/pages/_landing-page.scss */
+/* line 224, ../assets/sass/pages/_landing-page.scss */
 .view-display-id-block_1 .view-header .txt-re-news h2 {
   color: #851E5E;
   font-size: 22px;
 }
-/* line 209, ../assets/sass/pages/_landing-page.scss */
+/* line 230, ../assets/sass/pages/_landing-page.scss */
 .view-display-id-block_1 .view-header .txt-more-news-head {
   text-align: right;
   padding: 0;
 }
-/* line 213, ../assets/sass/pages/_landing-page.scss */
+/* line 234, ../assets/sass/pages/_landing-page.scss */
 .view-display-id-block_1 .view-header .txt-more-news-head h3, .view-display-id-block_1 .view-header .txt-more-news-head a {
   color: #851E5E;
   font-size: 22px;
 }
-/* line 217, ../assets/sass/pages/_landing-page.scss */
+/* line 238, ../assets/sass/pages/_landing-page.scss */
 .view-display-id-block_1 .view-header .txt-more-news-head h3 svg, .view-display-id-block_1 .view-header .txt-more-news-head a svg {
   font-size: 20px;
 }
 @media (max-width: 768px) {
-  /* line 209, ../assets/sass/pages/_landing-page.scss */
+  /* line 230, ../assets/sass/pages/_landing-page.scss */
   .view-display-id-block_1 .view-header .txt-more-news-head {
     display: none;
   }
 }
-/* line 228, ../assets/sass/pages/_landing-page.scss */
+/* line 249, ../assets/sass/pages/_landing-page.scss */
 .view-display-id-block_1 .view-content {
   float: left;
   width: 100%;
 }
 @media (max-width: 768px) {
-  /* line 233, ../assets/sass/pages/_landing-page.scss */
+  /* line 254, ../assets/sass/pages/_landing-page.scss */
   .view-display-id-block_1 .view-content .row {
     margin-bottom: 0;
   }
 }
-/* line 239, ../assets/sass/pages/_landing-page.scss */
+/* line 260, ../assets/sass/pages/_landing-page.scss */
 .view-display-id-block_1 .view-footer {
   text-transform: uppercase;
   float: left;
@@ -12055,43 +12066,43 @@ article.page {
   border-bottom: 1px solid #979797;
   display: none;
 }
-/* line 247, ../assets/sass/pages/_landing-page.scss */
+/* line 268, ../assets/sass/pages/_landing-page.scss */
 .view-display-id-block_1 .view-footer .txt-more-news-foot {
   text-align: right;
   padding: 0;
 }
-/* line 251, ../assets/sass/pages/_landing-page.scss */
+/* line 272, ../assets/sass/pages/_landing-page.scss */
 .view-display-id-block_1 .view-footer .txt-more-news-foot h3, .view-display-id-block_1 .view-footer .txt-more-news-foot a {
   color: #851E5E;
   font-size: 22px;
 }
-/* line 255, ../assets/sass/pages/_landing-page.scss */
+/* line 276, ../assets/sass/pages/_landing-page.scss */
 .view-display-id-block_1 .view-footer .txt-more-news-foot h3 svg, .view-display-id-block_1 .view-footer .txt-more-news-foot a svg {
   font-size: 20px;
 }
 @media (max-width: 768px) {
-  /* line 239, ../assets/sass/pages/_landing-page.scss */
+  /* line 260, ../assets/sass/pages/_landing-page.scss */
   .view-display-id-block_1 .view-footer {
     display: block;
   }
 }
 
-/* line 270, ../assets/sass/pages/_landing-page.scss */
+/* line 291, ../assets/sass/pages/_landing-page.scss */
 #views-bootstrap-people-directory-block-1 .people-row .inner-people-grid {
   background: #ffffff;
 }
 
-/* line 276, ../assets/sass/pages/_landing-page.scss */
+/* line 297, ../assets/sass/pages/_landing-page.scss */
 .views-field-field-evt-image .field--name-field-media-image {
   padding-bottom: 0;
 }
 
-/* line 282, ../assets/sass/pages/_landing-page.scss */
+/* line 303, ../assets/sass/pages/_landing-page.scss */
 .views-field-field-news-image2 .field--name-field-media-image {
   padding-bottom: 0;
 }
 
-/* line 288, ../assets/sass/pages/_landing-page.scss */
+/* line 309, ../assets/sass/pages/_landing-page.scss */
 .inner-people-grid .views-field-nothing-1 {
   margin-bottom: 10px;
 }
diff --git a/web/themes/asc_bootstrap/templates/node/node--event.html.twig b/web/themes/asc_bootstrap/templates/node/node--event.html.twig
index b45123d2b305e12584003151da7309a7be4b5f7e..b9646c0cda5dff7128aaef802e1ab22d8532cd4d 100644
--- a/web/themes/asc_bootstrap/templates/node/node--event.html.twig
+++ b/web/themes/asc_bootstrap/templates/node/node--event.html.twig
@@ -228,7 +228,28 @@
 
 
     </div>
-      {{ content|without('field_evt_image')|without('field_evt_location_2')|without('field_evt_date')|without('field_evt_date_range')|without('field_evt_time')|without('field_evt_social_share')  }}
+      {{ content|without('field_evt_image')|without('field_evt_location_2')|without('field_evt_date')|without('field_evt_date_range')|without('field_evt_time')|without('field_evt_social_share')|without('field_evt_taxonomy')|without('field_evt_taxonomy2')  }}
+
+      {% for item in content.field_evt_taxonomy %}
+        {% if item['#title'] %}
+          <div class="taxonomy-events">
+            <a href="/events?field_evt_taxonomy_target_id_1={{ item['#url']|render|split('/')|last }}">
+              {{ item['#title'] }}
+            </a>
+          </div>
+        {% endif %}
+      {% endfor %}
+
+      {% for item in content.field_evt_taxonomy2 %}
+        {% if item['#title'] %}
+          <div class="taxonomy-events">
+            <a href="/events?field_evt_taxonomy2_target_id={{ item['#url']|render|split('/')|last }}">
+              {{ item['#title'] }}
+            </a>
+          </div>
+        {% endif %}
+      {% endfor %}
+
       <hr/>
       {% if node.field_evt_social_share.value == 1 %}
         {{ content.field_evt_social_share }}
diff --git a/web/themes/asc_bootstrap/templates/node/node--news-story.html.twig b/web/themes/asc_bootstrap/templates/node/node--news-story.html.twig
index fd0ed0b827605bb9c356412f8fbc07b5989f9ec8..43aebf529b0c3b3619167a1985f3fd83e1017eb8 100644
--- a/web/themes/asc_bootstrap/templates/node/node--news-story.html.twig
+++ b/web/themes/asc_bootstrap/templates/node/node--news-story.html.twig
@@ -109,7 +109,28 @@
   </div>
   <div{{ content_attributes.addClass('content') }}>
     <div class="col-sm-8 col-sm-pull-4 news-cont">
-      {{ content|without('field_news_image2')|without('field_news_social_share') }}
+    {{ content|without('field_news_image2')|without('field_news_social_share')|without('field_news_terms_1')|without('field_news_terms_2') }}
+
+      {% for item in content.field_news_terms_1 %}
+        {% if item['#title'] %}
+          <div class="taxonomy-news">
+            <a href="/news?field_news_terms_1_target_id={{ item['#url']|render|split('/')|last }}">
+              {{ item['#title'] }}
+            </a>
+          </div>
+        {% endif %}
+      {% endfor %}
+
+      {% for item in content.field_news_terms_2 %}
+        {% if item['#title'] %}
+          <div class="taxonomy-news">
+            <a href="/news?field_news_terms_2_target_id={{ item['#url']|render|split('/')|last }}">
+              {{ item['#title'] }}
+            </a>
+          </div>
+        {% endif %}
+      {% endfor %}
+
       <hr/>
       {% if node.field_news_social_share.value == 1 %}
         {{ content.field_news_social_share }}
diff --git a/web/themes/asc_bootstrap/templates/paragraph/paragraph--call-out-box.html.twig b/web/themes/asc_bootstrap/templates/paragraph/paragraph--call-out-box.html.twig
index e7baec3c5eb37226a39b52f044b7a83704fe0d99..0c30866b0da3c5e3aa5e048ee25cd1dcfecce646 100644
--- a/web/themes/asc_bootstrap/templates/paragraph/paragraph--call-out-box.html.twig
+++ b/web/themes/asc_bootstrap/templates/paragraph/paragraph--call-out-box.html.twig
@@ -37,7 +37,7 @@
 #}
 
 {% if content.field_image_link[0]['#url'] %}
-  <a href="{{ content.field_image_link[0]['#url'] }}" title="{{ content.field_image_link.0['#title'] }}">
+  <a href="{{ content.field_image_link[0]['#url'] }}" title="{{ content.field_image_link.0['#title'] }}" class="img-link-wrapper">
 {% endif %}
     {{ content.field_bk_image }}
 
@@ -45,3 +45,5 @@
   </a>
 {% endif %}
 {{ content.field_image_link }}
+
+{#--{{ content.field_image_link.0 | truncate(100, true) }}--#}
diff --git a/web/themes/asc_bootstrap/templates/system/user.html.twig b/web/themes/asc_bootstrap/templates/system/user.html.twig
index c55ad46de3462270c4fc58dd16918497026bb26c..c3741240bddb09a61b1df43349f5665aaff76aa3 100644
--- a/web/themes/asc_bootstrap/templates/system/user.html.twig
+++ b/web/themes/asc_bootstrap/templates/system/user.html.twig
@@ -35,7 +35,9 @@
         </h1>
         {% if content.field_appointment.0 != '' %}
           <p class="bio-title">
-            {{ content.field_appointment.0 }}
+            <a href="/people?field_appointment_target_id[{{ content.field_appointment.0['#url']|render|split('/')|last }}]={{ content.field_appointment.0['#url']|render|split('/')|last }}">
+              {{ content.field_appointment.0['#title'] }}
+            </a>
           </p>
         {% endif %}
 
@@ -129,7 +131,15 @@
       {% endif %}
 
       {% if content.field_research_interests.0 != '' %}
-        {{ content.field_research_interests }}
+        {% for item in content.field_research_interests %}
+          {% if item['#title'] %}
+            <div class="research-interests-ppl">
+              <a href="/people?field_research_interests_target_id[{{ item['#url']|render|split('/')|last }}]={{ item['#url']|render|split('/')|last }}">
+                {{ item['#title'] }}
+              </a>
+            </div>
+          {% endif %}
+        {% endfor %}
       {% endif %}
     </div>