<?xml version="1.0"?>
<News hasArchived="true" page="7955" pageCount="10847" pageSize="10" timestamp="Thu, 01 Oct 2026 16:36:29 -0400" url="https://my3.my.umbc.edu/posts.xml?mode=activity&amp;page=7955&amp;range=30">
<NewsItem contentIssues="false" id="40667" important="false" status="posted" url="https://my3.my.umbc.edu/posts/40667">
<Title>WOFF 2.0 Evaluation Report Draft Published</Title>
<Body>
<![CDATA[
    <div class="html-content"><p>The <a href="http://www.w3.org/Fonts/WG/" rel="nofollow external" class="bo">WebFonts Working Group</a> has published a Working Draft of <a href="http://www.w3.org/TR/2014/WD-WOFF20ER-20140128/" rel="nofollow external" class="bo">WOFF 2.0 Evaluation Report</a>. Web Open Font Format (WOFF) 2.0 is a proposed update to the existing WOFF 1.0 with improved compression. This report lists requirements for successful deployment, evaluates how the requirement may be met, and examines the compression gains and tradeoffs vs. code complexity, encode and decode time. This document is non-normative. Learn more about the <a href="http://www.w3.org/Fonts/" rel="nofollow external" class="bo">Fonts Activity</a>.</p></div>
]]>
</Body>
<Summary>The WebFonts Working Group has published a Working Draft of WOFF 2.0 Evaluation Report. Web Open Font Format (WOFF) 2.0 is a proposed update to the existing WOFF 1.0 with improved compression....</Summary>
<Website>http://www.w3.org/blog/news/archives/3607</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/40667/guest@my.umbc.edu/4d5cca23711f383a75f733882466ddeb/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>design</Tag>
<Tag>development</Tag>
<Tag>home-page-stories</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>publication</Tag>
<Tag>sql</Tag>
<Tag>w3</Tag>
<Tag>web</Tag>
<Tag>web-design-and-applications</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 28 Jan 2014 09:38:49 -0500</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="40673" important="false" status="posted" url="https://my3.my.umbc.edu/posts/40673">
<Title>DealBook: Adding Up the Costs of Data Breaches</Title>
<Body>
<![CDATA[
    <div class="html-content">Companies victimized by cyberattacks face a big need to disclose information, both to the victims and to shareholders.<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fdealbook.nytimes.com%2F2014%2F01%2F28%2Fadding-up-the-costs-of-data-breaches%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+Adding+Up+the+Costs+of+Data+Breaches" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fdealbook.nytimes.com%2F2014%2F01%2F28%2Fadding-up-the-costs-of-data-breaches%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+Adding+Up+the+Costs+of+Data+Breaches" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fdealbook.nytimes.com%2F2014%2F01%2F28%2Fadding-up-the-costs-of-data-breaches%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+Adding+Up+the+Costs+of+Data+Breaches" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fdealbook.nytimes.com%2F2014%2F01%2F28%2Fadding-up-the-costs-of-data-breaches%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+Adding+Up+the+Costs+of+Data+Breaches" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fdealbook.nytimes.com%2F2014%2F01%2F28%2Fadding-up-the-costs-of-data-breaches%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=DealBook%3A+Adding+Up+the+Costs+of+Data+Breaches" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    </div>
]]>
</Body>
<Summary>Companies victimized by cyberattacks face a big need to disclose information, both to the victims and to shareholders.      </Summary>
<Website>http://dealbook.nytimes.com/2014/01/28/adding-up-the-costs-of-data-breaches/?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/40673/guest@my.umbc.edu/36e7b69d327ef3d7a178d7146f210922/api/pixel</TrackingUrl>
<Tag>blumenthal-richard</Tag>
<Tag>computer-security</Tag>
<Tag>credit-cards</Tag>
<Tag>customer-relations</Tag>
<Tag>cyberattacks-and-hackers</Tag>
<Tag>eastern-europe</Tag>
<Tag>identity-theft</Tag>
<Tag>legal-regulatory</Tag>
<Tag>michaels-stores-inc</Tag>
<Tag>neiman-marcus-group</Tag>
<Tag>new</Tag>
<Tag>retail-leisure</Tag>
<Tag>russia</Tag>
<Tag>shopping-and-retail</Tag>
<Tag>target-corporation</Tag>
<Tag>target-corporation-tgt-nyse</Tag>
<Tag>technology</Tag>
<Tag>top-headline-2</Tag>
<Tag>united-states</Tag>
<Tag>white-collar-watch</Tag>
<Tag>world-economic-forum</Tag>
<Tag>york</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 28 Jan 2014 09:33:37 -0500</PostedAt>
<EditAt>Tue, 28 Jan 2014 09:33:37 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="false" id="40261" important="false" status="posted" url="https://my3.my.umbc.edu/posts/40261">
<Title>First Global Microfinance Brigades @ UMBC</Title>
<Tagline>Cheers to our new family</Tagline>
<Body>
<![CDATA[
    <div class="html-content">It seemed like not so long ago a group of 5 people happen to stubble along with their friend's idea about starting a Microfinance Brigades chapter at UMBC. That friend, of course, is the president of this new org, Catherine Liou. However, the chapter wouldn't have made it as far as it did without her backing team of exec board that followed through with their word- Cynthia Lo, Queenie Tran, Mita Nagchaudhuri, Andrew Liem, and Christina Yi. Since then, it's been a family in the making. <br><br>Fast forward to the present and you're looking at a newly established club with a schedule trip to Honduras in May 2014. Why is this trip worth the investment and time? Well, it's the same reason why our exec team stuck to our word to get this org established. Social Investment Outreach. Specifically for this trip, our org will <span>fosters financial literacy programs, </span><span>establish <span>community banking system with access to loans, </span>and promote education to increase production and foster a culture of savings and </span><span>growth. Ultimately, you will have improved rural communities in Honduras through microfinance, cultural exchange and education.<br><br>So then, how do you become a part of it? Firstly, we'd love any support the community at UMBC can give us. Like our Facebook page, become a member on our group at MyUMBC, and join our Empowered.org page! Also, since this will be our first trip, we're constantly looking for active new members who'd like to join in on our family and possibly travel to Honduras! If you are interested in joining the org, or have any questions or comments, feel free to email the president at <a href="mailto:Cali1@umbc.edu">Cali1@umbc.edu</a>. We hope you join in on our opportunity to make a difference, and cheers to our new family! <br><br><br>Facebook Page URL: <a href="https://www.facebook.com/umbcmicrofinancebrigades">https://www.facebook.com/umbcmicrofinancebrigades</a><br><br>UMBC Group Page URL: </span><span><a href="http://my.umbc.edu/groups/gmfb" rel="nofollow external" class="bo">http://my.umbc.edu/groups/gmfb</a><br><br></span><span><span>Empowered.org URL:  
    <a href="http://www.globalbrigades.org/empowered/chapter/university-of-maryland-baltimore-county-microfinance-brigades-chapter/brigade/umbc-microfinance-brigade-june-2014">http://www.globalbrigades.org/empowered/chapter/university-of-maryland-baltimore-county-microfinance-brigades-chapter/brigade/umbc-microfinance-brigade-june-2014</a></span> <br></span>
    </div>
]]>
</Body>
<Summary>It seemed like not so long ago a group of 5 people happen to stubble along with their friend's idea about starting a Microfinance Brigades chapter at UMBC. That friend, of course, is the president...</Summary>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/40261/guest@my.umbc.edu/9f5a49116e50e113df09762514acc970/api/pixel</TrackingUrl>
<Group token="retired-800">Global Microfinance Brigades </Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-800</GroupUrl>
<AvatarUrl>https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/800/d33c10c1a53c1e860a631c00f02d748a/xsmall.png?1389797413</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/800/d33c10c1a53c1e860a631c00f02d748a/original.jpeg?1389797413</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/800/d33c10c1a53c1e860a631c00f02d748a/xxlarge.png?1389797413</AvatarUrl>
<AvatarUrl size="xlarge">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/800/d33c10c1a53c1e860a631c00f02d748a/xlarge.png?1389797413</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/800/d33c10c1a53c1e860a631c00f02d748a/large.png?1389797413</AvatarUrl>
<AvatarUrl size="medium">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/800/d33c10c1a53c1e860a631c00f02d748a/medium.png?1389797413</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/800/d33c10c1a53c1e860a631c00f02d748a/small.png?1389797413</AvatarUrl>
<AvatarUrl size="xsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/800/d33c10c1a53c1e860a631c00f02d748a/xsmall.png?1389797413</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/800/d33c10c1a53c1e860a631c00f02d748a/xxsmall.png?1389797413</AvatarUrl>
<Sponsor>Global Microfinance Brigades</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 28 Jan 2014 09:22:37 -0500</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="40663" important="false" status="posted" url="https://my3.my.umbc.edu/posts/40663">
<Title>Researcher of the Week: Mary Hester</Title>
<Tagline>Undergraduate researchers explore their interests!</Tagline>
<Body>
<![CDATA[
    <div class="html-content">
    <p>Meet Mary.  </p>
    <p>She is a Dance and INDS major and current Undergraduate Research Award (URA) scholar.  Her current research measures the benefits of dance lessons on children.  She is also a Linehan Artist Scholar, the President of the Dance Council of Majors and has served as a Welcome Week Leader for the past three years.</p>
    <p><strong>How did you know this was the project you wanted to do?</strong><br>I have always wanted to combine my passion for the Arts with my purpose to advance the Arts in education through policy. With the creation of my Interdisciplinary Studies Major titled “Arts Advocacy”, I knew that I wanted to do research that would help me grow as an advocate. I also love to teach dance, so I knew this project would be a lot of fun!<br><br><strong>Is this your first independent research/artistic project?</strong><br>This is my first independent research project of this type, but I previously received the Linehan Summer Research and Study Award to study dance for three weeks with Doug Varone and Dancers in New York.<br><br><strong>Do you get course credit for this work?</strong><br>Yes! This research will also be presented as my Interdisciplinary Studies Capstone.<br><br><strong>How did you hear about the Undergraduate Research Award (URA) program?</strong><br>I had attended URCAD several times and many of my friends had done research through the URA. After seeing their projects and learning about their experiences, I wanted to do it, too!<br><br><strong>What academic background did you have before you applied for the URA?</strong><br>I was a Junior when I applied to the URA, so I had completed most of my core and degree requirements. One of the classes that has helped me the most in completing the analytical portion of this research was POLI 301- Political Science Research Methods with Dr. Carolyn Forestiere. She became my URA mentor and has been infinitely helpful in designing, implementing, and completing this research.<br><br><strong>Was the application difficult to do?</strong><br>The application was easier than I thought it would be. I found it really helpful to attend the workshops provided, and would recommend working closely with your mentor while completing the application.<br><br><strong>What has been the hardest part about your research? </strong><br>The hardest part of my research was definitely coordinating with all the necessary people to implement my dance program within the Summer Learning Program. I began planning with the local YMCA in December, but by May they had gotten so busy that it was hard to schedule meetings about my research. I had to be persistent while also trying not to be bothersome, as I understood they had a lot they were trying to plan.<br><br><strong>What was the most unexpected thing?</strong><br>I thought that the children I worked with would like dancing, but I didn’t expect that on the last day they would all want to know where to take dance lessons and wanted to know if I would be coming back next summer! They were a little bit resistant at the beginning, so I wasn’t expecting that sort of reaction to the dance program in the end. It was unexpected, but I was so happy!<br><br><strong>How does your research relate to your work in other classes?</strong><br>Because I am an Interdisciplinary Studies Major, I designed my coursework to eventually lead up to this research project. I took classes in research, dance, sociology, political science, and social work that all related to my project in some way.<br><br><strong>What else are you involved in on campus?</strong><br>I am a Linehan Artist Scholar, the President of Dance Council of Majors, and have been a Welcome Week Leader for the past three years.<br><br><strong>What is your advice to other students about getting involved in research?</strong> <br>Don’t be afraid to ask for help!!! Everyone I have worked with on this project has been more than happy to help me and I am really grateful for that. It is easy to think that because you designed the project you shouldn’t ask for help, but that is not the case!<br><br><strong>What are your career goals?</strong><br>While I know that I want to be an advocate for the arts, I do not exactly know how I want to do this. In the Spring, I will be interning with Americans for the Arts working on arts education governmental affairs. I’m really looking forward to this experience helping me shape my career goals.<br><br><strong>Did you transfer to UMBC from another institution? Where?</strong><br>I started at UMBC as a freshman and will be graduating next May! <br><br>Read her abstract here...</p>
    </div>
]]>
</Body>
<Summary>Meet Mary.    She is a Dance and INDS major and current Undergraduate Research Award (URA) scholar.  Her current research measures the benefits of dance lessons on children.  She is also a Linehan...</Summary>
<Website>http://www.umbc.edu/undergrad_ed/research/ResearcherProfiles/maryHester.htm</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/40663/guest@my.umbc.edu/9c8e24d6e5db63e6a759f7950a907604/api/pixel</TrackingUrl>
<Group token="undergradresearch">Undergraduate Research</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/undergradresearch</GroupUrl>
<AvatarUrl>https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/xsmall.png?1600355057</AvatarUrl>
<AvatarUrl size="original">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/original.jpg?1600355057</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/xxlarge.png?1600355057</AvatarUrl>
<AvatarUrl size="xlarge">https://assets1-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/xlarge.png?1600355057</AvatarUrl>
<AvatarUrl size="large">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/large.png?1600355057</AvatarUrl>
<AvatarUrl size="medium">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/medium.png?1600355057</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/small.png?1600355057</AvatarUrl>
<AvatarUrl size="xsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/xsmall.png?1600355057</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/006/875606ced2b629148af4caa1a4e8dd3c/xxsmall.png?1600355057</AvatarUrl>
<Sponsor>Undergraduate Research</Sponsor>
<ThumbnailUrl size="xxlarge">https://assets2-my.umbc.edu/system/shared/thumbnails/news/000/040/663/26e87ce3ffff8cab875cc01616fad7ed/xxlarge.jpg?1390917785</ThumbnailUrl>
<ThumbnailUrl size="xlarge">https://assets2-my.umbc.edu/system/shared/thumbnails/news/000/040/663/26e87ce3ffff8cab875cc01616fad7ed/xlarge.jpg?1390917785</ThumbnailUrl>
<ThumbnailUrl size="large">https://assets1-my.umbc.edu/system/shared/thumbnails/news/000/040/663/26e87ce3ffff8cab875cc01616fad7ed/large.jpg?1390917785</ThumbnailUrl>
<ThumbnailUrl size="medium">https://assets2-my.umbc.edu/system/shared/thumbnails/news/000/040/663/26e87ce3ffff8cab875cc01616fad7ed/medium.jpg?1390917785</ThumbnailUrl>
<ThumbnailUrl size="small">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/040/663/26e87ce3ffff8cab875cc01616fad7ed/small.jpg?1390917785</ThumbnailUrl>
<ThumbnailUrl size="xsmall">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/040/663/26e87ce3ffff8cab875cc01616fad7ed/xsmall.jpg?1390917785</ThumbnailUrl>
<ThumbnailUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/040/663/26e87ce3ffff8cab875cc01616fad7ed/xxsmall.jpg?1390917785</ThumbnailUrl>
<PawCount>15</PawCount>
<CommentCount>2</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 28 Jan 2014 09:04:24 -0500</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="40662" important="false" status="posted" url="https://my3.my.umbc.edu/posts/40662">
<Title>6 Motivational Strategies for Self-Improvement</Title>
<Tagline>Wellness Article of the Week: Huffington Post Healthy Living</Tagline>
<Body>
<![CDATA[
    <div class="html-content">
    <p>“As human beings, we're always striving to be better. The most common self-improvement goals people set, particularly this time of year, are things like losing weight, improving our cholesterol numbers or blood pressure, or getting in shape for a marathon. These are body goals. They are concrete and easy to understand. Because we have metrics to measure things like weight loss, for example, it's easy to track our progress and stay motivated.</p>
    <p>Making "soul resolutions" is more challenging. These are the deeper aspects of self-growth. These would be things like trying to be less critical, more loving, more patient, or more optimistic. Soul resolutions are not so easy to measure. <br>And that can be a problem. Too often, when it comes to changing profound aspects of our attitudes, behavior, and character, we can get bored, uninspired, and discouraged after a while. We can't really tell sometimes if our efforts are "paying off."</p>
    <p>To avoid the boredom of spirit that sometimes accompanies profound changes you're trying to make on yourself, here are some simple strategies for staying motivated.” </p>
    <p><a href="http://www.huffingtonpost.com/brant-secunda-and-mark-allen/motivation_b_4652944.html?utm_hp_ref=healthy-living" rel="nofollow external" class="bo">Read more…<br></a></p>
    </div>
]]>
</Body>
<Summary>“As human beings, we're always striving to be better. The most common self-improvement goals people set, particularly this time of year, are things like losing weight, improving our cholesterol...</Summary>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/40662/guest@my.umbc.edu/8c3ebc72e94a520b10037cfed52f02b2/api/pixel</TrackingUrl>
<Group token="wellness">Wellness Initiative</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/wellness</GroupUrl>
<AvatarUrl>https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/172/7c77f048a2d02e784926184a82686fa0/xsmall.png?1504100162</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/172/7c77f048a2d02e784926184a82686fa0/original.jpg?1504100162</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/172/7c77f048a2d02e784926184a82686fa0/xxlarge.png?1504100162</AvatarUrl>
<AvatarUrl size="xlarge">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/172/7c77f048a2d02e784926184a82686fa0/xlarge.png?1504100162</AvatarUrl>
<AvatarUrl size="large">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/172/7c77f048a2d02e784926184a82686fa0/large.png?1504100162</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/172/7c77f048a2d02e784926184a82686fa0/medium.png?1504100162</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/172/7c77f048a2d02e784926184a82686fa0/small.png?1504100162</AvatarUrl>
<AvatarUrl size="xsmall">https://assets2-my.umbc.edu/system/shared/avatars/groups/000/000/172/7c77f048a2d02e784926184a82686fa0/xsmall.png?1504100162</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/172/7c77f048a2d02e784926184a82686fa0/xxsmall.png?1504100162</AvatarUrl>
<Sponsor>Wellness Initiative</Sponsor>
<ThumbnailUrl size="xxlarge">https://assets1-my.umbc.edu/system/shared/thumbnails/news/000/040/662/9ec04091466e231d20d349c52a689a21/xxlarge.jpg?1390917639</ThumbnailUrl>
<ThumbnailUrl size="xlarge">https://assets1-my.umbc.edu/system/shared/thumbnails/news/000/040/662/9ec04091466e231d20d349c52a689a21/xlarge.jpg?1390917639</ThumbnailUrl>
<ThumbnailUrl size="large">https://assets3-my.umbc.edu/system/shared/thumbnails/news/000/040/662/9ec04091466e231d20d349c52a689a21/large.jpg?1390917639</ThumbnailUrl>
<ThumbnailUrl size="medium">https://assets3-my.umbc.edu/system/shared/thumbnails/news/000/040/662/9ec04091466e231d20d349c52a689a21/medium.jpg?1390917639</ThumbnailUrl>
<ThumbnailUrl size="small">https://assets4-my.umbc.edu/system/shared/thumbnails/news/000/040/662/9ec04091466e231d20d349c52a689a21/small.jpg?1390917639</ThumbnailUrl>
<ThumbnailUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/thumbnails/news/000/040/662/9ec04091466e231d20d349c52a689a21/xsmall.jpg?1390917639</ThumbnailUrl>
<ThumbnailUrl size="xxsmall">https://assets1-my.umbc.edu/system/shared/thumbnails/news/000/040/662/9ec04091466e231d20d349c52a689a21/xxsmall.jpg?1390917639</ThumbnailUrl>
<PawCount>2</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>false</CommentsAllowed>
<PostedAt>Tue, 28 Jan 2014 09:01:03 -0500</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="40674" important="false" status="posted" url="https://my3.my.umbc.edu/posts/40674">
<Title>Bits Blog: Dell Moves Toward Cheap Networking</Title>
<Body>
<![CDATA[
    <div class="html-content">Dell wants to do the same thing to the networking business that the lower costs of open-source operating systems did to destroy the old computer server business.<br><div><table border="0"><tbody><tr><td>
    <a href="http://share.feedsportal.com/share/twitter/?u=http%3A%2F%2Fbits.blogs.nytimes.com%2F2014%2F01%2F28%2Fdell-moves-toward-cheap-networking%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+Dell+Moves+Toward+Cheap+Networking" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/twitter.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/facebook/?u=http%3A%2F%2Fbits.blogs.nytimes.com%2F2014%2F01%2F28%2Fdell-moves-toward-cheap-networking%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+Dell+Moves+Toward+Cheap+Networking" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/facebook.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/linkedin/?u=http%3A%2F%2Fbits.blogs.nytimes.com%2F2014%2F01%2F28%2Fdell-moves-toward-cheap-networking%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+Dell+Moves+Toward+Cheap+Networking" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/linkedin.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/gplus/?u=http%3A%2F%2Fbits.blogs.nytimes.com%2F2014%2F01%2F28%2Fdell-moves-toward-cheap-networking%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+Dell+Moves+Toward+Cheap+Networking" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/googleplus.png" style="max-width: 100%; height: auto;"></a> <a href="http://share.feedsportal.com/share/email/?u=http%3A%2F%2Fbits.blogs.nytimes.com%2F2014%2F01%2F28%2Fdell-moves-toward-cheap-networking%2F%3Fpartner%3Drss%26emc%3Drss&amp;t=Bits+Blog%3A+Dell+Moves+Toward+Cheap+Networking" rel="nofollow external" class="bo"><img src="http://res3.feedsportal.com/social/email.png" style="max-width: 100%; height: auto;"></a>
    </td></tr></tbody></table></div>
    <br><br><a href="http://da.feedsportal.com/r/187557104897/u/0/f/640387/c/34625/s/3673a493/sc/4/rc/1/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/187557104897/u/0/f/640387/c/34625/s/3673a493/sc/4/rc/1/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/187557104897/u/0/f/640387/c/34625/s/3673a493/sc/4/rc/2/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/187557104897/u/0/f/640387/c/34625/s/3673a493/sc/4/rc/2/rc.img" style="max-width: 100%; height: auto;"></a><br><a href="http://da.feedsportal.com/r/187557104897/u/0/f/640387/c/34625/s/3673a493/sc/4/rc/3/rc.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/187557104897/u/0/f/640387/c/34625/s/3673a493/sc/4/rc/3/rc.img" style="max-width: 100%; height: auto;"></a><br><br><a href="http://da.feedsportal.com/r/187557104897/u/0/f/640387/c/34625/s/3673a493/a2.htm" rel="nofollow external" class="bo"><img src="http://da.feedsportal.com/r/187557104897/u/0/f/640387/c/34625/s/3673a493/a2.img" style="max-width: 100%; height: auto;"></a>
    </div>
]]>
</Body>
<Summary>Dell wants to do the same thing to the networking business that the lower costs of open-source operating systems did to destroy the old computer server business.      </Summary>
<Website>http://bits.blogs.nytimes.com/2014/01/28/dell-moves-toward-cheap-networking/?partner=rss&amp;emc=rss</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/40674/guest@my.umbc.edu/9702198e2dec1a654948042978e8e032/api/pixel</TrackingUrl>
<Tag>cisco-systems-inc</Tag>
<Tag>cisco-systems-inc-csco-nasdaq</Tag>
<Tag>cloud-computing</Tag>
<Tag>dell-inc</Tag>
<Tag>dell-inc-dell-nasdaq</Tag>
<Tag>enterprise-computing</Tag>
<Tag>hewlett-packard-company</Tag>
<Tag>hewlett-packard-company-hpq-nyse</Tag>
<Tag>juniper-networks-inc</Tag>
<Tag>juniper-networks-inc-jnpr-nyse</Tag>
<Tag>new</Tag>
<Tag>open-source-software</Tag>
<Tag>technology</Tag>
<Tag>york</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 28 Jan 2014 09:00:38 -0500</PostedAt>
<EditAt>Tue, 28 Jan 2014 12:44:39 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="41056" important="false" status="posted" url="https://my3.my.umbc.edu/posts/41056">
<Title>Setting Up a Local Mirror for Composer Packages With Satis</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <p>Installing all your PHP libraries with Composer is a great way to save time. But larger projects automatically tested and run at each commit to your software version control (SVC) system will take a long time to install all the required packages from the Internet. You want to run your tests as soon as possible through your continuous integration (CI) system so that you have fast feedback and quick reactions on failure. In this tutorial we will set up a local mirror to proxy all your packages required in your project's <code>composer.json</code> file. This will make our CI work much faster, install the packages over the local network or even hosted on the same machine, and make sure we have the specific versions of the packages always available.</p>
    <p></p>
    <hr>
    <h2>What Is Satis?</h2>
    <p>Satis is the name of the application we will use to mirror the various repositories for our project. It sits as a proxy between the Internet and your composer. Our solution will create a local mirror of a few packages and instruct our composer to use it instead of the sources found on the Internet.</p>
    <p>Here is an image that says more than a thousand words.</p>
    
    <img src="http://cdn.tutsplus.com/net/uploads/2014/01/Architecture.png" alt="Architecture" width="600" height="197" style="max-width: 100%; height: auto;"><br>
    
    <p>Our project will use composer as usual. It will be configured to use the local Satis server as the primary source. If a package is found there, it will be installed from there. If not, we will let composer use the default packagist.org to retrieve the package.</p>
    <hr>
    <h2>Getting Satis</h2>
    <p>Satis is available through composer, so installing it is very simple. In the attached source code archive, you will find Satis installed in the <code>Sources/Satis</code> folder. First we will install composer itself.</p>
    <pre>$ curl -sS <a href="https://getcomposer.org/installer">https://getcomposer.org/installer</a> | php&#x000A;    #!/usr/bin/env php All settings correct for using Composer Downloading...&#x000A;     Composer successfully installed to: /home/csaba/Personal/Programming/NetTuts/Setting up a local mirror for Composer packages with Satis/Sources/Satis/composer.phar Use it: php composer.phar</pre>
    <p>Then we will install Satis.</p>
    <pre>$ php composer.phar create-project composer/satis --stability=dev --keep-vcs Installing composer/satis (dev-master eddb78d52e8f7ea772436f2320d6625e18d5daf5)&#x000A;      - Installing composer/satis (dev-master master)&#x000A;        Cloning master&#x000A;     Created project in /home/csaba/Personal/Programming/NetTuts/Setting up a local mirror for Composer packages with Satis/Sources/Satis/satis Loading composer repositories with package information Installing dependencies (including require-dev) from lock file&#x000A;      - Installing symfony/process (dev-master 27b0fc6)&#x000A;        Cloning 27b0fc645a557b2fc7bc7735cfb05505de9351be&#x000A;    &#x000A;      - Installing symfony/finder (v2.4.0-BETA1)&#x000A;        Downloading: 100%&#x000A;    &#x000A;      - Installing symfony/console (dev-master f44cc6f)&#x000A;        Cloning f44cc6fabdaa853335d7f54f1b86c99622db518a&#x000A;    &#x000A;      - Installing seld/jsonlint (1.1.1)&#x000A;        Downloading: 100%&#x000A;    &#x000A;      - Installing justinrainbow/json-schema (1.1.0)&#x000A;        Downloading: 100%&#x000A;    &#x000A;      - Installing composer/composer (dev-master f8be812)&#x000A;        Cloning f8be812a496886c84918d6dd1b50db5c16da3cc3&#x000A;    &#x000A;      - Installing twig/twig (v1.14.1)&#x000A;        Downloading: 100%&#x000A;     symfony/console suggests installing symfony/event-dispatcher () Generating autoload files</pre>
    <hr>
    <h2>Configuring Satis</h2>
    <p>Satis is configured by a JSON file very similar to composer. You can use whatever name you want for your file and specify it for usage later. We will use "<code>mirrored-packages.conf</code>".</p>
    <pre>{&#x000A;        "name": "NetTuts Composer Mirror",&#x000A;        "homepage": "<a href="http://localhost:4680">http://localhost:4680</a>",&#x000A;    &#x000A;        "repositories": [&#x000A;            { "type": "vcs", "url": "<a href="https://github.com/SynetoNet/monolog">https://github.com/SynetoNet/monolog</a>" },&#x000A;            { "type": "composer", "url": "<a href="https://packagist.org">https://packagist.org</a>" }&#x000A;        ],&#x000A;    &#x000A;        "require": {&#x000A;            "monolog/monolog": "syneto-dev",&#x000A;            "mockery/mockery": "*",&#x000A;            "phpunit/phpunit": "*"&#x000A;        },&#x000A;        "require-dependencies": true&#x000A;    }</pre>
    <p>Let's analyze this configuration file.</p>
    <ul>
    <li>
    <code>name</code> - represents a string that will be shown on the web interface of our mirror.</li>
    <li>
    <code>homepage</code> - is the web address where our packages will be kept. This does not tell our web server to use that address and port, it is rather just information of a working configuration. We will set up the access to it on that addres and port later.</li>
    <li>
    <code>repositories</code> - a list of repositories ordered by preference. In our example, the first repository is a Github fork of the monolog logging libraries. It has some modifications and we want to use that specific fork when installing monolog. The type of this repository is "<code>vcs</code>". The second repository is of type "<code>composer</code>". Its URL is the default packagist.org site.</li>
    <li>
    <code>require</code> - lists the packages we want to mirror. It can represent a specific package with a specific version or branch, or any version for that matter. It uses the same syntax as your "<code>require</code>" or "<code>require-dev</code>" in your <code>composer.json</code>.</li>
    <li>
    <code>require-dependencies</code> - is the final option in our example. It will tell Satis to mirror not only the packages we specified in the "<code>require</code>" section but also all their dependencies.</li>
    </ul>
    <p>To quickly try out our settings we first need to tell Satis to create the mirrors. Run this command in the folder where you installed Satis.</p>
    <pre>$ php ./satis/bin/satis build ./mirrored-packages.conf ./packages-mirror Scanning packages Writing packages.json Writing web view</pre>
    <p>While the process is taking place, you will see how Satis mirrors each found version of the required packages. Be patient it may take a while to build all those packages.</p>
    <p>Satis requires that <code>date.timezone</code> to be specified in the <code>php.ini</code> file, so make sure it is and set to your local timezone. Otherwise an error will appear.</p>
    <pre>[Twig_Error_Runtime]&#x000A;      An exception has been thrown during the rendering of a template&#x000A;    ("date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set) function.</pre>
    <p>Then we can run a PHP server instance in our console pointing to the recently created repository. PHP 5.4 or newer is required.</p>
    <pre>$ php -S localhost:4680 -t ./packages-mirror/ PHP 5.4.22-pl0-gentoo Development Server started at Sun Dec  8 14:47:48 2013 Listening on <a href="http://localhost:4680">http://localhost:4680</a> Document root is /home/csaba/Personal/Programming/NetTuts/Setting up a local mirror for Composer packages with Satis/Sources/Satis/packages-mirror Press Ctrl-C to quit.&#x000A;    [Sun Dec  8 14:48:09 2013] 127.0.0.1:56999 [200]: /&#x000A;    [Sun Dec  8 14:48:09 2013] 127.0.0.1:57000 [404]: /favicon.ico - No such file or directory</pre>
    <p>And we can now browse our mirrored packages and even search for specific ones by pointing our web browser to <code><a href="http://localhost:4680">http://localhost:4680</a></code>:</p>
    
    <img src="http://cdn.tutsplus.com/net/uploads/2014/01/MirrorWebpage.png" alt="MirrorWebpage" width="600" height="567" style="max-width: 100%; height: auto;"><br>
    
    <hr>
    <h2>Let's Host It on Apache</h2>
    <p>If you have a running Apache at hand, creating a virtual host for Satis will be quite simple.</p>
    <pre>Listen 4680&#x000A;    &#x000A;    &lt;Directory "/path/to/your/packages-mirror"&gt; Options -Indexes FollowSymLinks AllowOverride all Order allow,deny Allow from all&#x000A;    &lt;/Directory&gt;&#x000A;    &#x000A;    &lt;VirtualHost *:4680&gt; DocumentRoot "/path/to/your/packages-mirror" ServerName 127.0.0.1:4680 ServerAdmin <a href="mailto:admin@example.com">admin@example.com</a>&#x000A;     ErrorLog syslog:user&#x000A;    &#x000A;    &lt;/VirtualHost&gt;</pre>
    <p>We just use a <code>.conf</code> file like this, put in Apache's <code>conf.d</code> folder, usually <code>/etc/apache2/conf.d</code>. It creates a virtual host on the 4680 port and points it to our folder. Of course you can use whatever port you want.</p>
    <hr>
    <h2>Updating Our Mirrors</h2>
    <p>Satis can not automatically update the mirrors unless we tell it. So the easiest way, on any UNIX like system, is to just add a cron job to your system. That would be very easy, and just a simple script to execute our update command.</p>
    <pre>#!/bin/bash php /full/path/to/satis/bin/satis build \&#x000A;    /full/path/to/mirrored-packages.conf \&#x000A;    /full/path/to/packages-mirror</pre>
    <p>The drawback of this solution is that it is static. We have to manually update the <code>mirrored-packages.conf</code> every time we add another package to our project's <code>composer.json</code>. If you are part of a team in a company with a big project and a continuous integration server, you can't rely on people remembering to add the packages on the server. They may not even have permissions to access the CI infrastructure.</p>
    <hr>
    <h2>Dynamically Updating Satis Configuration</h2>
    <p>It's time for a PHP TDD exercise. If you just want your code ready and running, check out the source code attached to this tutorial.</p>
    <pre>require_once __DIR__ . '/../../../../vendor/autoload.php';&#x000A;     class SatisUpdaterTest extends PHPUnit_Framework_TestCase {&#x000A;        function testBehavior() {&#x000A;            $this-&gt;assertTrue(true);&#x000A;        }&#x000A;    }</pre>
    <p>As usual we start with a degenerative test, just enough to make sure we have a working testing framework. You may notice that I have quite a strange looking require_once line, this is because I want to avoid having to reinstall PHPUnit and Mockery for each small project. So I have them in a <code>vendor</code> folder in my <code>NetTuts</code>' root. You should just install them with composer and drop the <code>require_once</code> line altogether.</p>
    <pre>class SatisUpdaterTest extends PHPUnit_Framework_TestCase {&#x000A;    	function testDefaultConfigFile() {&#x000A;    		$expected = '{&#x000A;        "name": "NetTuts Composer Mirror",&#x000A;        "homepage": "<a href="http://localhost:4680">http://localhost:4680</a>",&#x000A;    &#x000A;        "repositories": [&#x000A;            { "type": "vcs", "url": "<a href="https://github.com/SynetoNet/monolog">https://github.com/SynetoNet/monolog</a>" },&#x000A;            { "type": "composer", "url": "<a href="https://packagist.org">https://packagist.org</a>" }&#x000A;        ],&#x000A;    &#x000A;        "require": {&#x000A;        },&#x000A;        "require-dependencies": true&#x000A;    }';&#x000A;    		$actual = $this-&gt;parseComposerConf('');&#x000A;    		$this-&gt;assertEquals($expected, $actual);&#x000A;    	}&#x000A;    }</pre>
    <p>That looks about right. All the fields except "<code>require</code>" are static. We need to generate only the packages. The repositories are pointing to our private git clones and to packagist as needed. Managing those is more of a sysadmin job than a software developer's.</p>
    <p>Of course this fails with:</p>
    <pre>PHP Fatal error:  Call to undefined method SatisUpdaterTest::parseComposerConf()</pre>
    <p>Fixing that is easy.</p>
    <pre>private function parseComposerConf($string) {&#x000A;    }</pre>
    <p>I just added an empty method with the required name, as private, to our test class. Cool, but now we have another error.</p>
    <pre>PHPUnit_Framework_ExpectationFailedException : Failed asserting that null matches expected '{ ... }'</pre>
    <p>So, null does not match our string containing all that default configuration.</p>
    <pre>private function parseComposerConf($string) {&#x000A;        return '{&#x000A;    "name": "NetTuts Composer Mirror",&#x000A;    "homepage": "<a href="http://localhost:4680">http://localhost:4680</a>",&#x000A;    &#x000A;    "repositories": [&#x000A;        { "type": "vcs", "url": "<a href="https://github.com/SynetoNet/monolog">https://github.com/SynetoNet/monolog</a>" },&#x000A;        { "type": "composer", "url": "<a href="https://packagist.org">https://packagist.org</a>" }&#x000A;    ],&#x000A;    &#x000A;    "require": {&#x000A;    },&#x000A;    "require-dependencies": true&#x000A;    }';&#x000A;    }</pre>
    <p>OK, that works. All tests are passing.</p>
    <pre>PHPUnit 3.7.28 by Sebastian Bergmann. Time: 15 ms, Memory: 2.50Mb OK (1 test, 1 assertion)</pre>
    <p>But we introduced a horrible duplication. All that static text in two places, written character by character in two different places. Let's fix it:</p>
    <pre>class SatisUpdaterTest extends PHPUnit_Framework_TestCase {&#x000A;    	static $DEFAULT_CONFIG = '{&#x000A;        "name": "NetTuts Composer Mirror",&#x000A;        "homepage": "<a href="http://localhost:4680">http://localhost:4680</a>",&#x000A;    &#x000A;        "repositories": [&#x000A;            { "type": "vcs", "url": "<a href="https://github.com/SynetoNet/monolog">https://github.com/SynetoNet/monolog</a>" },&#x000A;            { "type": "composer", "url": "<a href="https://packagist.org">https://packagist.org</a>" }&#x000A;        ],&#x000A;    &#x000A;        "require": {&#x000A;        },&#x000A;        "require-dependencies": true&#x000A;    }';&#x000A;    &#x000A;    	function testDefaultConfigFile() {&#x000A;    		$expected =  self::$DEFAULT_CONFIG;&#x000A;    &#x000A;    		$actual = $this-&gt;parseComposerConf('');&#x000A;    		$this-&gt;assertEquals($expected, $actual);&#x000A;    	}&#x000A;    &#x000A;    	private function parseComposerConf($string) {&#x000A;    		return self::$DEFAULT_CONFIG;&#x000A;    	}&#x000A;    }</pre>
    <p>Ahhh! That's better.</p>
    <pre>	function testEmptyRequiredPackagesInComposerJsonWillProduceDefaultConfiguration() {&#x000A;        $expected = self::$DEFAULT_CONFIG;&#x000A;    &#x000A;        $actual = $this-&gt;parseComposerConf('{"require": {}}');&#x000A;        $this-&gt;assertEquals($expected, $actual);&#x000A;    }</pre>
    <p>Well. That also passes. But it also highlights some duplication and useless assignment.</p>
    <pre>	function testDefaultConfigFile() {&#x000A;        $actual = $this-&gt;parseComposerConf('');&#x000A;        $this-&gt;assertEquals(self::$DEFAULT_CONFIG, $actual);&#x000A;    }&#x000A;     function testEmptyRequiredPackagesInComposerJsonWillProduceDefaultConfiguration() {&#x000A;        $actual = $this-&gt;parseComposerConf('{"require": {}}');&#x000A;        $this-&gt;assertEquals(self::$DEFAULT_CONFIG, $actual);&#x000A;    }</pre>
    <p>We inlined the <code>$expected</code> variable. <code>$actual</code> could also be inlined, but I like it better this way. It keeps the focus on what is tested.</p>
    <p>Now we have another problem. The next test I want to write would look like this:</p>
    <pre>function testARequiredPackageInComposerWillBeInSatisAlso() {&#x000A;        $actual = $this-&gt;parseComposerConf(&#x000A;        '{"require": {&#x000A;            "Mockery/Mockery": "&gt;=0.7.2"&#x000A;        }}');&#x000A;        $this-&gt;assertContains('"Mockery/Mockery": "&gt;=0.7.2"', $actual);&#x000A;    }</pre>
    <p>But after writing the simple implementation, we will notice it requires <code>json_decode()</code> and <code>json_encode()</code>. And of course these functions reformat our string and matching strings will be difficult at best. We have to take a step back.</p>
    <pre>function testDefaultConfigFile() {&#x000A;        $actual = $this-&gt;parseComposerConf('');&#x000A;        $this-&gt;assertJsonStringEqualsJsonString($this-&gt;jsonRecode(self::$DEFAULT_CONFIG), $actual);&#x000A;    }&#x000A;     function testEmptyRequiredPackagesInComposerJsonWillProduceDefaultConfiguration() {&#x000A;        $actual = $this-&gt;parseComposerConf('{"require": {}}');&#x000A;        $this-&gt;assertJsonStringEqualsJsonString($this-&gt;jsonRecode(self::$DEFAULT_CONFIG), $actual);&#x000A;    }&#x000A;     private function parseComposerConf($jsonConfig) {&#x000A;        return $this-&gt;jsonRecode(self::$DEFAULT_CONFIG);&#x000A;    }&#x000A;     private function jsonRecode($json) {&#x000A;        return json_encode(json_decode($json, true));&#x000A;    }</pre>
    <p>We changed our assertion method to compare JSON strings and we also recoded our <code>$actual</code> variable. <code>ParseComposerConf()</code> was also modified to use this method. You will see in a moment how it helps us. Our next test becomes more JSON specific.</p>
    <pre>function testARequiredPackageInComposerWillBeInSatisAlso() {&#x000A;        $actual = $this-&gt;parseComposerConf(&#x000A;            '{"require": {&#x000A;                "Mockery/Mockery": "&gt;=0.7.2"&#x000A;            }}');&#x000A;        $this-&gt;assertEquals('&gt;=0.7.2', json_decode($actual, true)['require']['Mockery/Mockery']);&#x000A;    }</pre>
    <p>And making this test pass, along with the rest of the tests, is quite easy, again.</p>
    <pre>private function parseComposerConf($jsonConfig) {&#x000A;        $addedConfig = json_decode($jsonConfig, true);&#x000A;        $config = json_decode(self::$DEFAULT_CONFIG, true);&#x000A;        if (isset($addedConfig['require'])) {&#x000A;            $config['require'] = $addedConfig['require'];&#x000A;        }&#x000A;        return json_encode($config);&#x000A;    }</pre>
    <p>We take the input JSON string, decode it, and if it contains a "<code>require</code>" field we use that in our Satis configuration file instead. But we may want to mirror all versions of a package, not just the last one. So maybe we want to modify our test to check that the version is "*" in Satis, regardless of what exact version is in <code>composer.json</code>.</p>
    <pre>function testARequiredPackageInComposerWillBeInSatisAlso() {&#x000A;        $actual = $this-&gt;parseComposerConf(&#x000A;            '{"require": {&#x000A;                "Mockery/Mockery": "&gt;=0.7.2"&#x000A;            }}');&#x000A;        $this-&gt;assertEquals('*', json_decode($actual, true)['require']['Mockery/Mockery']);&#x000A;    }</pre>
    <p>That obviously fails with a cool message:</p>
    <pre>PHPUnit_Framework_ExpectationFailedException : Failed asserting that two strings are equal. Expected :* Actual   :&gt;=0.7.2</pre>
    <p>Now, we need to actually edit our JSON before re-encoding it.</p>
    <pre>private function parseComposerConf($jsonConfig) {&#x000A;        $addedConfig = json_decode($jsonConfig, true);&#x000A;        $config = json_decode(self::$DEFAULT_CONFIG, true);&#x000A;        $config = $this-&gt;addNewRequires($addedConfig, $config);&#x000A;        return json_encode($config);&#x000A;    }&#x000A;     private function toAllVersions($config) {&#x000A;        foreach ($config['require'] as $package =&gt; $version) {&#x000A;            $config['require'][$package] = '*';&#x000A;        }&#x000A;        return $config;&#x000A;    }&#x000A;     private function addNewRequires($addedConfig, $config) {&#x000A;        if (isset($addedConfig['require'])) {&#x000A;            $config['require'] = $addedConfig['require'];&#x000A;            $config = $this-&gt;toAllVersions($config);&#x000A;        }&#x000A;        return $config;&#x000A;    }</pre>
    <p>To make the test pass we have to iterate over each element of the required packages array and set their version to '*'. See method <code>toAllVersion()</code> for more details. And to speed up this tutorial a little bit, we also extracted some private methods in the same step. This way, <code>parseComoserConf()</code> becomes very descriptive and easy to understand. We could also inline <code>$config</code> into the arguments of <code>addNewRequires()</code>, but for aesthetic reasons I left it on two lines.</p>
    <p>But what about "<code>require-dev</code>" in <code>composer.json</code>?</p>
    <pre>function testARquiredDevPackageInComposerWillBeInSatisAlso() {&#x000A;        $actual = $this-&gt;parseComposerConf(&#x000A;            '{"require-dev": {&#x000A;                "Mockery/Mockery": "&gt;=0.7.2",&#x000A;                "phpunit/phpunit": "3.7.28"&#x000A;            }}');&#x000A;        $this-&gt;assertEquals('*', json_decode($actual, true)['require']['Mockery/Mockery']);&#x000A;        $this-&gt;assertEquals('*', json_decode($actual, true)['require']['phpunit/phpunit']);&#x000A;    }</pre>
    <p>That obviously fails. We can make it pass with just copy/pasting our if condition in <code>addNewRequires()</code>:</p>
    <pre>private function addNewRequires($addedConfig, $config) {&#x000A;        if (isset($addedConfig['require'])) {&#x000A;            $config['require'] = $addedConfig['require'];&#x000A;            $config = $this-&gt;toAllVersions($config);&#x000A;        }&#x000A;        if (isset($addedConfig['require-dev'])) {&#x000A;            $config['require'] = $addedConfig['require-dev'];&#x000A;            $config = $this-&gt;toAllVersions($config);&#x000A;        }&#x000A;        return $config;&#x000A;    }</pre>
    <p>Yep, that makes it pass, but those duplicated if statements are nasty looking. Let's deal with them.</p>
    <pre>private function addNewRequires($addedConfig, $config) {&#x000A;        $config = $this-&gt;addRequire($addedConfig, 'require', $config);&#x000A;        $config = $this-&gt;addRequire($addedConfig, 'require-dev', $config);&#x000A;        return $config;&#x000A;    }&#x000A;     private function addRequire($addedConfig, $string, $config) {&#x000A;        if (isset($addedConfig[$string])) {&#x000A;            $config['require'] = $addedConfig[$string];&#x000A;            $config = $this-&gt;toAllVersions($config);&#x000A;        }&#x000A;        return $config;&#x000A;    }</pre>
    <p>We can be happy again, tests are green and we refactored our code. I think only one test is left to be written. What if we have both "<code>require</code>" and "<code>require-dev</code>" sections in <code>composer.json</code>?</p>
    <pre>function testItCanParseComposerJsonWithBothSections() {&#x000A;        $actual = $this-&gt;parseComposerConf(&#x000A;            '{"require": {&#x000A;                "Mockery/Mockery": "&gt;=0.7.2"&#x000A;                },&#x000A;            "require-dev": {&#x000A;                "phpunit/phpunit": "3.7.28"&#x000A;            }}');&#x000A;        $this-&gt;assertEquals('*', json_decode($actual, true)['require']['Mockery/Mockery']);&#x000A;        $this-&gt;assertEquals('*', json_decode($actual, true)['require']['phpunit/phpunit']);&#x000A;    }</pre>
    <p>That fails because the packages set by "<code>require-dev</code>" will overwrite those of "<code>require</code>" and we will have an error: </p>
    <pre>Undefined index: Mockery/Mockery</pre>
    <p>Just add a plus sign to merge the arrays, and we are done.</p>
    <pre>private function addRequire($addedConfig, $string, $config) {&#x000A;        if (isset($addedConfig[$string])) {&#x000A;            $config['require'] += $addedConfig[$string];&#x000A;            $config = $this-&gt;toAllVersions($config);&#x000A;        }&#x000A;        return $config;&#x000A;    }</pre>
    <p>Tests are passing. Our logic is finished. All we left to do is to extract the methods into their own file and class. The final version of the tests and the <code>SatisUpdater</code> class can be found in the attached source code. </p>
    <p>We can now modify our cron script to load our parser and run it on our <code>composer.json</code>. This will be specific to your projects' particular folders. Here is an example you can adapt to your system.</p>
    <pre>#!/usr/local/bin/php&#x000A;    &#x000A;    &lt;?php require_once __DIR__ . '/Configuration.php';&#x000A;    &#x000A;    $outputDir = '/path/to/your/packages-mirror';&#x000A;    $composerJsonFile = '/path/to/your/projects/composer.json';&#x000A;    $satisConf = '/path/to/your/mirrored-packages.conf';&#x000A;    &#x000A;    $satisUpdater = new SatisUpdater();&#x000A;    $conf = $satisUpdater-&gt;parseComposerConf(file_get_contents($composerJsonFile)); file_put_contents($satisConf, $conf);&#x000A;     system(sprintf('/path/to/satis/bin/satis build %s %s', $satisConf, $outputDir), $retval); exit($retval);</pre>
    <hr>
    <h2>Making Your Project Use the Mirror</h2>
    <p>We talked about a lot of things in this article, but we did not mention how we will instruct our project to use the mirror instead of the Internet. You know, the default is packagist.org? Unless we do something like this:</p>
    <pre>   "repositories": [&#x000A;            {&#x000A;                "type": "composer",&#x000A;                "url": "<a href="http://your-mirror-server:4680">http://your-mirror-server:4680</a>"&#x000A;            }&#x000A;        ],</pre>
    <p>That will make your mirror the first choise for composer. But adding just that into the <code>composer.json</code> of your project will not disable access to packagist.org. If a package can not be found on the local mirror, it will be downloaded from the Internet. If you wish to block this feature, you may also want to add the following line to the repositories section above:</p>
    <pre>"packagist": false</pre>
    <hr>
    <h2>Final Thoughts</h2>
    <p>That's it. Local mirror, with automatic adapting and updating packages. Your colleagues will never have to wait a long time while they or the CI server installs all the requirements of your projects. Have fun.</p>
    </div>
]]>
</Body>
<Summary>Installing all your PHP libraries with Composer is a great way to save time. But larger projects automatically tested and run at each commit to your software version control (SVC) system will take...</Summary>
<Website>http://code.tutsplus.com/tutorials/setting-up-a-local-mirror-for-composer-packages-with-satis--net-36726</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/41056/guest@my.umbc.edu/f2618511f0d80e07c7f59c40f2197dca/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>wed</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 28 Jan 2014 09:00:35 -0500</PostedAt>
<EditAt>Tue, 28 Jan 2014 09:00:34 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="40664" important="false" status="posted" url="https://my3.my.umbc.edu/posts/40664">
<Title>Setting Up a Local Mirror for Composer Packages With Satis</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <a href="http://rss.buysellads.com/click.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=36726&amp;c=558272831" rel="nofollow external" class="bo"><img src="http://rss.buysellads.com/img.php?z=1260013&amp;k=d754f1e9ba63a736ba8ff5ece958f7dd&amp;a=36726&amp;c=558272831" alt="" style="max-width: 100%; height: auto;"></a><p>Installing all your PHP libraries with Composer is a great way to save time. But larger projects automatically tested and run at each commit to your software version control (SVC) system will take a long time to install all the required packages from the Internet. You want to run your tests as soon as possible through your continuous integration (CI) system so that you have fast feedback and quick reactions on failure. In this tutorial we will set up a local mirror to proxy all your packages required in your project’s <code>composer.json</code> file. This will make our CI work much faster, install the packages over the local network or even hosted on the same machine, and make sure we have the specific versions of the packages always available.</p>
    <p></p>
    <hr>
    <h2>What Is Satis?</h2>
    <p>Satis is the name of the application we will use to mirror the various repositories for our project. It sits as a proxy between the Internet and your composer. Our solution will create a local mirror of a few packages and instruct our composer to use it instead of the sources found on the Internet.</p>
    <p>Here is an image that says more than a thousand words.</p>  <img src="http://cdn.tutsplus.com/net/uploads/2014/01/Architecture.png" alt="Architecture" width="600" height="197" style="max-width: 100%; height: auto;"><br> <p>Our project will use composer as usual. It will be configured to use the local Satis server as the primary source. If a package is found there, it will be installed from there. If not, we will let composer use the default packagist.org to retrieve the package.</p>
    <hr>
    <h2>Getting Satis</h2>
    <p>Satis is available through composer, so installing it is very simple. In the attached source code archive, you will find Satis installed in the <code>Sources/Satis</code> folder. First we will install composer itself.</p>
    <pre>$ curl -sS <a href="https://getcomposer.org/installer">https://getcomposer.org/installer</a> | php&#x000A;    #!/usr/bin/env php All settings correct for using Composer Downloading...&#x000A;     Composer successfully installed to: /home/csaba/Personal/Programming/NetTuts/Setting up a local mirror for Composer packages with Satis/Sources/Satis/composer.phar Use it: php composer.phar&#x000A;    </pre>
    <p>Then we will install Satis.</p>
    <pre>$ php composer.phar create-project composer/satis --stability=dev --keep-vcs Installing composer/satis (dev-master eddb78d52e8f7ea772436f2320d6625e18d5daf5)&#x000A;      - Installing composer/satis (dev-master master)&#x000A;        Cloning master&#x000A;     Created project in /home/csaba/Personal/Programming/NetTuts/Setting up a local mirror for Composer packages with Satis/Sources/Satis/satis Loading composer repositories with package information Installing dependencies (including require-dev) from lock file&#x000A;      - Installing symfony/process (dev-master 27b0fc6)&#x000A;        Cloning 27b0fc645a557b2fc7bc7735cfb05505de9351be&#x000A;    &#x000A;      - Installing symfony/finder (v2.4.0-BETA1)&#x000A;        Downloading: 100%&#x000A;    &#x000A;      - Installing symfony/console (dev-master f44cc6f)&#x000A;        Cloning f44cc6fabdaa853335d7f54f1b86c99622db518a&#x000A;    &#x000A;      - Installing seld/jsonlint (1.1.1)&#x000A;        Downloading: 100%&#x000A;    &#x000A;      - Installing justinrainbow/json-schema (1.1.0)&#x000A;        Downloading: 100%&#x000A;    &#x000A;      - Installing composer/composer (dev-master f8be812)&#x000A;        Cloning f8be812a496886c84918d6dd1b50db5c16da3cc3&#x000A;    &#x000A;      - Installing twig/twig (v1.14.1)&#x000A;        Downloading: 100%&#x000A;     symfony/console suggests installing symfony/event-dispatcher () Generating autoload files&#x000A;    </pre>
    <hr>
    <h2>Configuring Satis</h2>
    <p>Satis is configured by a JSON file very similar to composer. You can use whatever name you want for your file and specify it for usage later. We will use “<code>mirrored-packages.conf</code>“.</p>
    <pre>{&#x000A;        "name": "NetTuts Composer Mirror",&#x000A;        "homepage": "<a href="http://localhost:4680">http://localhost:4680</a>",&#x000A;    &#x000A;        "repositories": [&#x000A;            { "type": "vcs", "url": "<a href="https://github.com/SynetoNet/monolog">https://github.com/SynetoNet/monolog</a>" },&#x000A;            { "type": "composer", "url": "<a href="https://packagist.org">https://packagist.org</a>" }&#x000A;        ],&#x000A;    &#x000A;        "require": {&#x000A;            "monolog/monolog": "syneto-dev",&#x000A;            "mockery/mockery": "*",&#x000A;            "phpunit/phpunit": "*"&#x000A;        },&#x000A;        "require-dependencies": true&#x000A;    }</pre>
    <p>Let’s analyze this configuration file.</p>
    <ul>
    <li>
    <code>name</code> – represents a string that will be shown on the web interface of our mirror.</li>
    <li>
    <code>homepage</code> – is the web address where our packages will be kept. This does not tell our web server to use that address and port, it is rather just information of a working configuration. We will set up the access to it on that addres and port later.</li>
    <li>
    <code>repositories</code> – a list of repositories ordered by preference. In our example, the first repository is a Github fork of the monolog logging libraries. It has some modifications and we want to use that specific fork when installing monolog. The type of this repository is “<code>vcs</code>“. The second repository is of type “<code>composer</code>“. Its URL is the default packagist.org site.</li>
    <li>
    <code>require</code> – lists the packages we want to mirror. It can represent a specific package with a specific version or branch, or any version for that matter. It uses the same syntax as your “<code>require</code>” or “<code>require-dev</code>” in your <code>composer.json</code>.</li>
    <li>
    <code>require-dependencies</code> – is the final option in our example. It will tell Satis to mirror not only the packages we specified in the “<code>require</code>” section but also all their dependencies.</li>
    </ul>
    <p>To quickly try out our settings we first need to tell Satis to create the mirrors. Run this command in the folder where you installed Satis.</p>
    <pre>$ php ./satis/bin/satis build ./mirrored-packages.conf ./packages-mirror Scanning packages Writing packages.json Writing web view&#x000A;    </pre>
    <p>While the process is taking place, you will see how Satis mirrors each found version of the required packages. Be patient it may take a while to build all those packages.</p>
    <p>Satis requires that <code>date.timezone</code> to be specified in the <code>php.ini</code> file, so make sure it is and set to your local timezone. Otherwise an error will appear.</p>
    <pre>[Twig_Error_Runtime]&#x000A;      An exception has been thrown during the rendering of a template&#x000A;    ("date_default_timezone_get(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set) function. </pre>
    <p>Then we can run a PHP server instance in our console pointing to the recently created repository. PHP 5.4 or newer is required.</p>
    <pre>$ php -S localhost:4680 -t ./packages-mirror/ PHP 5.4.22-pl0-gentoo Development Server started at Sun Dec  8 14:47:48 2013 Listening on <a href="http://localhost:4680">http://localhost:4680</a> Document root is /home/csaba/Personal/Programming/NetTuts/Setting up a local mirror for Composer packages with Satis/Sources/Satis/packages-mirror Press Ctrl-C to quit.&#x000A;    [Sun Dec  8 14:48:09 2013] 127.0.0.1:56999 [200]: /&#x000A;    [Sun Dec  8 14:48:09 2013] 127.0.0.1:57000 [404]: /favicon.ico - No such file or directory&#x000A;    </pre>
    <p>And we can now browse our mirrored packages and even search for specific ones by pointing our web browser to <code><a href="http://localhost:4680">http://localhost:4680</a></code>:</p>  <img src="http://cdn.tutsplus.com/net/uploads/2014/01/MirrorWebpage.png" alt="MirrorWebpage" width="600" height="567" style="max-width: 100%; height: auto;"><br> <hr>
    <h2>Let’s Host It on Apache</h2>
    <p>If you have a running Apache at hand, creating a virtual host for Satis will be quite simple.</p>
    <pre>Listen 4680&#x000A;    &#x000A;    &lt;Directory "/path/to/your/packages-mirror"&gt; Options -Indexes FollowSymLinks AllowOverride all Order allow,deny Allow from all&#x000A;    &lt;/Directory&gt;&#x000A;    &#x000A;    &lt;VirtualHost *:4680&gt; DocumentRoot "/path/to/your/packages-mirror" ServerName 127.0.0.1:4680 ServerAdmin <a href="mailto:admin@example.com">admin@example.com</a>&#x000A;     ErrorLog syslog:user&#x000A;    &#x000A;    &lt;/VirtualHost&gt;&#x000A;    </pre>
    <p>We just use a <code>.conf</code> file like this, put in Apache’s <code>conf.d</code> folder, usually <code>/etc/apache2/conf.d</code>. It creates a virtual host on the 4680 port and points it to our folder. Of course you can use whatever port you want.</p>
    <hr>
    <h2>Updating Our Mirrors</h2>
    <p>Satis can not automatically update the mirrors unless we tell it. So the easiest way, on any UNIX like system, is to just add a cron job to your system. That would be very easy, and just a simple script to execute our update command.</p>
    <pre>#!/bin/bash php /full/path/to/satis/bin/satis build \&#x000A;    /full/path/to/mirrored-packages.conf \&#x000A;    /full/path/to/packages-mirror</pre>
    <p>The drawback of this solution is that it is static. We have to manually update the <code>mirrored-packages.conf</code> every time we add another package to our project’s <code>composer.json</code>. If you are part of a team in a company with a big project and a continuous integration server, you can’t rely on people remembering to add the packages on the server. They may not even have permissions to access the CI infrastructure.</p>
    <hr>
    <h2>Dynamically Updating Satis Configuration</h2>
    <p>It’s time for a PHP TDD exercise. If you just want your code ready and running, check out the source code attached to this tutorial.</p>
    <pre>require_once __DIR__ . '/../../../../vendor/autoload.php';&#x000A;     class SatisUpdaterTest extends PHPUnit_Framework_TestCase {&#x000A;        function testBehavior() {&#x000A;            $this-&gt;assertTrue(true);&#x000A;        }&#x000A;    }</pre>
    <p>As usual we start with a degenerative test, just enough to make sure we have a working testing framework. You may notice that I have quite a strange looking require_once line, this is because I want to avoid having to reinstall PHPUnit and Mockery for each small project. So I have them in a <code>vendor</code> folder in my <code>NetTuts</code>‘ root. You should just install them with composer and drop the <code>require_once</code> line altogether.</p>
    <pre>class SatisUpdaterTest extends PHPUnit_Framework_TestCase {&#x000A;    	function testDefaultConfigFile() {&#x000A;    		$expected = '{&#x000A;        "name": "NetTuts Composer Mirror",&#x000A;        "homepage": "<a href="http://localhost:4680">http://localhost:4680</a>",&#x000A;    &#x000A;        "repositories": [&#x000A;            { "type": "vcs", "url": "<a href="https://github.com/SynetoNet/monolog">https://github.com/SynetoNet/monolog</a>" },&#x000A;            { "type": "composer", "url": "<a href="https://packagist.org">https://packagist.org</a>" }&#x000A;        ],&#x000A;    &#x000A;        "require": {&#x000A;        },&#x000A;        "require-dependencies": true&#x000A;    }';&#x000A;    		$actual = $this-&gt;parseComposerConf('');&#x000A;    		$this-&gt;assertEquals($expected, $actual);&#x000A;    	}&#x000A;    }</pre>
    <p>That looks about right. All the fields except “<code>require</code>” are static. We need to generate only the packages. The repositories are pointing to our private git clones and to packagist as needed. Managing those is more of a sysadmin job than a software developer’s.</p>
    <p>Of course this fails with:</p>
    <pre>PHP Fatal error:  Call to undefined method SatisUpdaterTest::parseComposerConf()</pre>
    <p>Fixing that is easy.</p>
    <pre>private function parseComposerConf($string) {&#x000A;    }</pre>
    <p>I just added an empty method with the required name, as private, to our test class. Cool, but now we have another error.</p>
    <pre>PHPUnit_Framework_ExpectationFailedException : Failed asserting that null matches expected '{ ... }'</pre>
    <p>So, null does not match our string containing all that default configuration.</p>
    <pre>private function parseComposerConf($string) {&#x000A;        return '{&#x000A;    "name": "NetTuts Composer Mirror",&#x000A;    "homepage": "<a href="http://localhost:4680">http://localhost:4680</a>",&#x000A;    &#x000A;    "repositories": [&#x000A;        { "type": "vcs", "url": "<a href="https://github.com/SynetoNet/monolog">https://github.com/SynetoNet/monolog</a>" },&#x000A;        { "type": "composer", "url": "<a href="https://packagist.org">https://packagist.org</a>" }&#x000A;    ],&#x000A;    &#x000A;    "require": {&#x000A;    },&#x000A;    "require-dependencies": true&#x000A;    }';&#x000A;    }</pre>
    <p>OK, that works. All tests are passing.</p>
    <pre>PHPUnit 3.7.28 by Sebastian Bergmann. Time: 15 ms, Memory: 2.50Mb OK (1 test, 1 assertion)</pre>
    <p>But we introduced a horrible duplication. All that static text in two places, written character by character in two different places. Let’s fix it:</p>
    <pre>class SatisUpdaterTest extends PHPUnit_Framework_TestCase {&#x000A;    	static $DEFAULT_CONFIG = '{&#x000A;        "name": "NetTuts Composer Mirror",&#x000A;        "homepage": "<a href="http://localhost:4680">http://localhost:4680</a>",&#x000A;    &#x000A;        "repositories": [&#x000A;            { "type": "vcs", "url": "<a href="https://github.com/SynetoNet/monolog">https://github.com/SynetoNet/monolog</a>" },&#x000A;            { "type": "composer", "url": "<a href="https://packagist.org">https://packagist.org</a>" }&#x000A;        ],&#x000A;    &#x000A;        "require": {&#x000A;        },&#x000A;        "require-dependencies": true&#x000A;    }';&#x000A;    &#x000A;    	function testDefaultConfigFile() {&#x000A;    		$expected =  self::$DEFAULT_CONFIG;&#x000A;    &#x000A;    		$actual = $this-&gt;parseComposerConf('');&#x000A;    		$this-&gt;assertEquals($expected, $actual);&#x000A;    	}&#x000A;    &#x000A;    	private function parseComposerConf($string) {&#x000A;    		return self::$DEFAULT_CONFIG;&#x000A;    	}&#x000A;    }</pre>
    <p>Ahhh! That’s better.</p>
    <pre>	function testEmptyRequiredPackagesInComposerJsonWillProduceDefaultConfiguration() {&#x000A;        $expected = self::$DEFAULT_CONFIG;&#x000A;    &#x000A;        $actual = $this-&gt;parseComposerConf('{"require": {}}');&#x000A;        $this-&gt;assertEquals($expected, $actual);&#x000A;    }</pre>
    <p>Well. That also passes. But it also highlights some duplication and useless assignment.</p>
    <pre>	function testDefaultConfigFile() {&#x000A;        $actual = $this-&gt;parseComposerConf('');&#x000A;        $this-&gt;assertEquals(self::$DEFAULT_CONFIG, $actual);&#x000A;    }&#x000A;     function testEmptyRequiredPackagesInComposerJsonWillProduceDefaultConfiguration() {&#x000A;        $actual = $this-&gt;parseComposerConf('{"require": {}}');&#x000A;        $this-&gt;assertEquals(self::$DEFAULT_CONFIG, $actual);&#x000A;    }</pre>
    <p>We inlined the <code>$expected</code> variable. <code>$actual</code> could also be inlined, but I like it better this way. It keeps the focus on what is tested.</p>
    <p>Now we have another problem. The next test I want to write would look like this:</p>
    <pre>function testARequiredPackageInComposerWillBeInSatisAlso() {&#x000A;        $actual = $this-&gt;parseComposerConf(&#x000A;        '{"require": {&#x000A;            "Mockery/Mockery": "&gt;=0.7.2"&#x000A;        }}');&#x000A;        $this-&gt;assertContains('"Mockery/Mockery": "&gt;=0.7.2"', $actual);&#x000A;    }</pre>
    <p>But after writing the simple implementation, we will notice it requires <code>json_decode()</code> and <code>json_encode()</code>. And of course these functions reformat our string and matching strings will be difficult at best. We have to take a step back.</p>
    <pre>function testDefaultConfigFile() {&#x000A;        $actual = $this-&gt;parseComposerConf('');&#x000A;        $this-&gt;assertJsonStringEqualsJsonString($this-&gt;jsonRecode(self::$DEFAULT_CONFIG), $actual);&#x000A;    }&#x000A;     function testEmptyRequiredPackagesInComposerJsonWillProduceDefaultConfiguration() {&#x000A;        $actual = $this-&gt;parseComposerConf('{"require": {}}');&#x000A;        $this-&gt;assertJsonStringEqualsJsonString($this-&gt;jsonRecode(self::$DEFAULT_CONFIG), $actual);&#x000A;    }&#x000A;     private function parseComposerConf($jsonConfig) {&#x000A;        return $this-&gt;jsonRecode(self::$DEFAULT_CONFIG);&#x000A;    }&#x000A;     private function jsonRecode($json) {&#x000A;        return json_encode(json_decode($json, true));&#x000A;    }</pre>
    <p>We changed our assertion method to compare JSON strings and we also recoded our <code>$actual</code> variable. <code>ParseComposerConf()</code> was also modified to use this method. You will see in a moment how it helps us. Our next test becomes more JSON specific.</p>
    <pre>function testARequiredPackageInComposerWillBeInSatisAlso() {&#x000A;        $actual = $this-&gt;parseComposerConf(&#x000A;            '{"require": {&#x000A;                "Mockery/Mockery": "&gt;=0.7.2"&#x000A;            }}');&#x000A;        $this-&gt;assertEquals('&gt;=0.7.2', json_decode($actual, true)['require']['Mockery/Mockery']);&#x000A;    }</pre>
    <p>And making this test pass, along with the rest of the tests, is quite easy, again.</p>
    <pre>private function parseComposerConf($jsonConfig) {&#x000A;        $addedConfig = json_decode($jsonConfig, true);&#x000A;        $config = json_decode(self::$DEFAULT_CONFIG, true);&#x000A;        if (isset($addedConfig['require'])) {&#x000A;            $config['require'] = $addedConfig['require'];&#x000A;        }&#x000A;        return json_encode($config);&#x000A;    }</pre>
    <p>We take the input JSON string, decode it, and if it contains a “<code>require</code>” field we use that in our Satis configuration file instead. But we may want to mirror all versions of a package, not just the last one. So maybe we want to modify our test to check that the version is “*” in Satis, regardless of what exact version is in <code>composer.json</code>.</p>
    <pre>function testARequiredPackageInComposerWillBeInSatisAlso() {&#x000A;        $actual = $this-&gt;parseComposerConf(&#x000A;            '{"require": {&#x000A;                "Mockery/Mockery": "&gt;=0.7.2"&#x000A;            }}');&#x000A;        $this-&gt;assertEquals('*', json_decode($actual, true)['require']['Mockery/Mockery']);&#x000A;    }</pre>
    <p>That obviously fails with a cool message:</p>
    <pre>PHPUnit_Framework_ExpectationFailedException : Failed asserting that two strings are equal. Expected :* Actual   :&gt;=0.7.2</pre>
    <p>Now, we need to actually edit our JSON before re-encoding it.</p>
    <pre>private function parseComposerConf($jsonConfig) {&#x000A;        $addedConfig = json_decode($jsonConfig, true);&#x000A;        $config = json_decode(self::$DEFAULT_CONFIG, true);&#x000A;        $config = $this-&gt;addNewRequires($addedConfig, $config);&#x000A;        return json_encode($config);&#x000A;    }&#x000A;     private function toAllVersions($config) {&#x000A;        foreach ($config['require'] as $package =&gt; $version) {&#x000A;            $config['require'][$package] = '*';&#x000A;        }&#x000A;        return $config;&#x000A;    }&#x000A;     private function addNewRequires($addedConfig, $config) {&#x000A;        if (isset($addedConfig['require'])) {&#x000A;            $config['require'] = $addedConfig['require'];&#x000A;            $config = $this-&gt;toAllVersions($config);&#x000A;        }&#x000A;        return $config;&#x000A;    }</pre>
    <p>To make the test pass we have to iterate over each element of the required packages array and set their version to ‘*’. See method <code>toAllVersion()</code> for more details. And to speed up this tutorial a little bit, we also extracted some private methods in the same step. This way, <code>parseComoserConf()</code> becomes very descriptive and easy to understand. We could also inline <code>$config</code> into the arguments of <code>addNewRequires()</code>, but for aesthetic reasons I left it on two lines.</p>
    <p>But what about “<code>require-dev</code>” in <code>composer.json</code>?</p>
    <pre>function testARquiredDevPackageInComposerWillBeInSatisAlso() {&#x000A;        $actual = $this-&gt;parseComposerConf(&#x000A;            '{"require-dev": {&#x000A;                "Mockery/Mockery": "&gt;=0.7.2",&#x000A;                "phpunit/phpunit": "3.7.28"&#x000A;            }}');&#x000A;        $this-&gt;assertEquals('*', json_decode($actual, true)['require']['Mockery/Mockery']);&#x000A;        $this-&gt;assertEquals('*', json_decode($actual, true)['require']['phpunit/phpunit']);&#x000A;    }</pre>
    <p>That obviously fails. We can make it pass with just copy/pasting our if condition in <code>addNewRequires()</code>:</p>
    <pre>private function addNewRequires($addedConfig, $config) {&#x000A;        if (isset($addedConfig['require'])) {&#x000A;            $config['require'] = $addedConfig['require'];&#x000A;            $config = $this-&gt;toAllVersions($config);&#x000A;        }&#x000A;        if (isset($addedConfig['require-dev'])) {&#x000A;            $config['require'] = $addedConfig['require-dev'];&#x000A;            $config = $this-&gt;toAllVersions($config);&#x000A;        }&#x000A;        return $config;&#x000A;    }</pre>
    <p>Yep, that makes it pass, but those duplicated if statements are nasty looking. Let’s deal with them.</p>
    <pre>private function addNewRequires($addedConfig, $config) {&#x000A;        $config = $this-&gt;addRequire($addedConfig, 'require', $config);&#x000A;        $config = $this-&gt;addRequire($addedConfig, 'require-dev', $config);&#x000A;        return $config;&#x000A;    }&#x000A;     private function addRequire($addedConfig, $string, $config) {&#x000A;        if (isset($addedConfig[$string])) {&#x000A;            $config['require'] = $addedConfig[$string];&#x000A;            $config = $this-&gt;toAllVersions($config);&#x000A;        }&#x000A;        return $config;&#x000A;    }</pre>
    <p>We can be happy again, tests are green and we refactored our code. I think only one test is left to be written. What if we have both “<code>require</code>” and “<code>require-dev</code>” sections in <code>composer.json</code>?</p>
    <pre>function testItCanParseComposerJsonWithBothSections() {&#x000A;        $actual = $this-&gt;parseComposerConf(&#x000A;            '{"require": {&#x000A;                "Mockery/Mockery": "&gt;=0.7.2"&#x000A;                },&#x000A;            "require-dev": {&#x000A;                "phpunit/phpunit": "3.7.28"&#x000A;            }}');&#x000A;        $this-&gt;assertEquals('*', json_decode($actual, true)['require']['Mockery/Mockery']);&#x000A;        $this-&gt;assertEquals('*', json_decode($actual, true)['require']['phpunit/phpunit']);&#x000A;    }</pre>
    <p>That fails because the packages set by “<code>require-dev</code>” will overwrite those of “<code>require</code>” and we will have an error:</p>
    <pre>Undefined index: Mockery/Mockery</pre>
    <p>Just add a plus sign to merge the arrays, and we are done.</p>
    <pre>private function addRequire($addedConfig, $string, $config) {&#x000A;        if (isset($addedConfig[$string])) {&#x000A;            $config['require'] += $addedConfig[$string];&#x000A;            $config = $this-&gt;toAllVersions($config);&#x000A;        }&#x000A;        return $config;&#x000A;    }</pre>
    <p>Tests are passing. Our logic is finished. All we left to do is to extract the methods into their own file and class. The final version of the tests and the <code>SatisUpdater</code> class can be found in the attached source code.</p>
    <p>We can now modify our cron script to load our parser and run it on our <code>composer.json</code>. This will be specific to your projects’ particular folders. Here is an example you can adapt to your system.</p>
    <pre>#!/usr/local/bin/php&#x000A;    &#x000A;    &lt;?php require_once __DIR__ . '/Configuration.php';&#x000A;    &#x000A;    $outputDir = '/path/to/your/packages-mirror';&#x000A;    $composerJsonFile = '/path/to/your/projects/composer.json';&#x000A;    $satisConf = '/path/to/your/mirrored-packages.conf';&#x000A;    &#x000A;    $satisUpdater = new SatisUpdater();&#x000A;    $conf = $satisUpdater-&gt;parseComposerConf(file_get_contents($composerJsonFile)); file_put_contents($satisConf, $conf);&#x000A;     system(sprintf('/path/to/satis/bin/satis build %s %s', $satisConf, $outputDir), $retval); exit($retval);&#x000A;    </pre>
    <hr>
    <h2>Making Your Project Use the Mirror</h2>
    <p>We talked about a lot of things in this article, but we did not mention how we will instruct our project to use the mirror instead of the Internet. You know, the default is packagist.org? Unless we do something like this:</p>
    <pre>   "repositories": [&#x000A;            {&#x000A;                "type": "composer",&#x000A;                "url": "<a href="http://your-mirror-server:4680">http://your-mirror-server:4680</a>"&#x000A;            }&#x000A;        ],&#x000A;    </pre>
    <p>That will make your mirror the first choise for composer. But adding just that into the <code>composer.json</code> of your project will not disable access to packagist.org. If a package can not be found on the local mirror, it will be downloaded from the Internet. If you wish to block this feature, you may also want to add the following line to the repositories section above:</p>
    <pre>"packagist": false</pre>
    <hr>
    <h2>Final Thoughts</h2>
    <p>That’s it. Local mirror, with automatic adapting and updating packages. Your colleagues will never have to wait a long time while they or the CI server installs all the requirements of your projects. Have fun.</p>
    </div>
]]>
</Body>
<Summary>Installing all your PHP libraries with Composer is a great way to save time. But larger projects automatically tested and run at each commit to your software version control (SVC) system will take...</Summary>
<Website>http://feedproxy.google.com/~r/nettuts/~3/HhXIibR1I24/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/40664/guest@my.umbc.edu/55ea852f7a0a9f37a6dffca9b4c6b500/api/pixel</TrackingUrl>
<Tag>composer</Tag>
<Tag>css</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>local-mirrors</Tag>
<Tag>mysql</Tag>
<Tag>php</Tag>
<Tag>satis</Tag>
<Tag>sql</Tag>
<Tag>tutorials</Tag>
<Tag>wed</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 28 Jan 2014 09:00:34 -0500</PostedAt>
<EditAt>Tue, 28 Jan 2014 09:00:34 -0500</EditAt>
</NewsItem>

<NewsItem contentIssues="true" id="40658" important="false" status="posted" url="https://my3.my.umbc.edu/posts/40658">
<Title>&#8220;The Eighth Wonder Of The World!&#8221; Smashing Conference NYC 2014</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <table width="650">
    <tbody>
    <tr>
    <td>
    <div>
    <img src="http://statisches.auslieferung.commindo-media-ressourcen.de/advertisement.gif" alt="" style="max-width: 100%; height: auto;"><br><a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=1" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=1" alt="" style="max-width: 100%; height: auto;"></a> <a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=2" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=2" alt="" style="max-width: 100%; height: auto;"></a> <a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=3" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=3" alt="" style="max-width: 100%; height: auto;"></a>
    </div>
    </td>
    </tr>
    </tbody>
    </table>
    <p><a href="http://smashingconf.com/ny-2014/" rel="nofollow external" class="bo">SmashingConf NYC 2014</a> won’t solve all complex problems, but once it’s over you’ll know how to conquer yours. Our new conference in New York has 1 track, 2 conference days, 7 workshops, 18 excellent speakers and just 350 available tickets. With a heavy focus on networking and <strong>practical takeaways from real-life projects</strong>, you really don’t want to miss out on this one. <a href="http://smashingconf.com/ny-2014/registration" rel="nofollow external" class="bo">To the tickets.</a></p>
    <h3>About The Conference</h3>
    <p>When we organize a conference, we make sure that it provides a lot of value for everybody involved. <strong>We don’t care about volatile trends</strong> and we don’t believe in overnight success stories. Every success requires hard work and many <strong>failures</strong> along the way. There are lessons learned, takeaways, and  problems solved, but also many sketches and designs and ideas and prototypes thrown away because they didn’t work. We are interested in <strong>how problems are solved</strong>—ideas that failed, and <em>why</em> exactly they failed and what decisions were chosen instead.</p>
    <p><a href="http://smashingconf.com/ny-2014/" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2014/01/smashingconf-nyc-june-2014.png" width="520" height="460" alt="Smashing Conference New York 2014" style="max-width: 100%; height: auto;"></a><br><em><a href="http://smashingconf.com/ny-2014" rel="nofollow external" class="bo">SmashingConf NYC 2014</a> is a two-day event taking place at the TimesCenter in the very heart of New York. We won’t conquer all complex issues, but you’ll learn how to conquer yours.</em></p>
    <p>And this is what the conference is about: lessons learned in <strong>front-end, UX, workflow</strong> and other design-related disciplines. This is what we encourage our speakers to share and what we are all going to explore in the conversations before, during and after the conference days.</p>
    <p><strong>Networking is important</strong>, and we’ll provide many opportunities for networking throughout the conference. Ah, and the party — oh, the party! You’ll remember that one! Taking place on June 17–18th 2014 in the lovely <em>TimesCenter</em> just next to Times Square in New York City, the conference will be nothing short of smashing. <em>Booo-yah, baby!</em></p>
    <p><a href="http://smashingconf.com/ny-2014/registration" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2014/01/get-the-tickets.png" width="270" height="103" alt="To the tickets" style="max-width: 100%; height: auto;"></a></p>
    <h3>First Confirmed Speakers</h3>
    <p>Okay. Ready for the first confirmed speakers? Get set. Go!</p>
    <p><a href="http://smashingconf.com/ny-2014/speakers" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2014/01/first-ny-speakers-smashingconf.jpg" width="500" height="343" alt="First Speakers in SmashingConf New York City 2014" style="max-width: 100%; height: auto;"></a><br><em>First confirmed speakers, Brian Suda and Divya Manian. Divya might even volunteer to run the legendary party in the evening — you never know!</em></p>
    <ul>
    <li>
    <strong>Brian Suda</strong><br><span>(Data visualization, SVG)</span>
    </li>
    <li>
    <strong>Divya Manian</strong><br><span>(HTML5 Boilerplate, Adobe)</span>
    </li>
    <li>
    <strong>Scott Jehl</strong><br><span>(Responsive Web design</span>)</li>
    <li>
    <strong>Oliver Reichenstein</strong><br><span>(UX, typography, iA Writer)</span>
    </li>
    <li>
    <strong>Aarron Walter</strong><br><span>(User experience)</span>
    </li>
    <li>
    <strong>Jonathan Hoefler</strong><br><span>(Typography, H&amp;FJ)</span>
    </li>
    <li>
    <strong>Andy Hume</strong><br><span>(Front-end optimization)</span>
    </li>
    <li>
    <strong>Cassie McDaniel</strong><br><span>(Storytelling, UX, Mozilla)</span>
    </li>
    <li>
    <strong>Tim Brown</strong><br><span>(Web typography)</span>
    </li>
    <li>
    <strong>Eva-Lotta Lamm</strong><br><span>(Sketching, UX, UI, Google)</span>
    </li>
    <li>
    <strong>Jonathan Snook</strong><br><span>(Front-end development)</span>
    </li>
    <li>
    <strong>Mark Boulton</strong><br><span>(Grids, Web design)</span>
    </li>
    <li>
    <strong>Dan Rose</strong><br><span>(Photoshop, visual design)</span>
    </li>
    <li>
    <strong>Mystery Speaker</strong><br><span>(Someone you <em>definitely</em> know.)</span>
    </li>
    <li><span>…more speakers will be announced soon!</span></li>
    </ul>
    <p><a href="http://smashingconf.com/ny-2014/registration" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2014/01/get-the-tickets.png" width="270" height="103" alt="To the tickets" style="max-width: 100%; height: auto;"></a></p>
    <h3>Hands-On Workshops</h3>
    <p>We’ll also host <a href="http://smashingconf.com/ny-2014/workshops" rel="nofollow external" class="bo">hands-on full-day workshops</a> with practical techniques taught by masters of the craft. Be it responsive HTML newsletters, Photoshop techniques for responsive design, SVG techniques, or strategies for delightful UX, we carefully selected topics that will help you become better at what you do. So if you are going to attend the conference, why not attend a workshop as well?</p>
    <p>In fact, we reserved 50 <strong>early-bird tickets</strong> for $549, and if you <strong>book a workshop</strong> too, you’ll save $100 off the conference + workshop ticket price. Well, enough already. Tickets are on sale now, you know.</p>
    <p><a href="http://smashingconf.com/ny-2014/locations" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2014/01/timesquare.jpg" alt="Times Center" style="max-width: 100%; height: auto;"></a><br><em>If you always wanted to visit New York, or just happen to live around the corner (well, more or less), that’s just the opportunity you’ve been waiting for. <a href="https://shop.smashingmagazine.com/smashing-conference-new-york-2014.html" rel="nofollow external" class="bo">Grab your ticket.</a></em></p>
    <h3>Why This Conference Is For You</h3>
    <p>The conference is for you because you’ll learn many valuable techniques for your workflow, and you’ll meet fantastic, like-minded people from the industry. You’ll learn:</p>
    <ol>
    <li>Strategies for building <strong>fast responsive websites</strong>,</li>
    <li>Smart <strong>SVG</strong> techniques for scalable, future-proof designs,</li>
    <li>Clever <strong>Photoshop</strong> techniques for RWD workflow,</li>
    <li>Tricks to design and build <strong>responsive HTML newsletters</strong>,</li>
    <li>Insights about effective and smart problem-solving,</li>
    <li>Hands-on techniques for <strong>sketching interfaces</strong>,</li>
    <li>Techniques and guidelines for good Web typography,</li>
    <li>Guidelines for smarter front-end and CSS architecture,</li>
    <li>Advanced <strong>front-end tooling and setup</strong>,</li>
    <li>Guidelines for delightful, engaging UX,</li>
    <li>Mistakes and lessons learned from large projects,</li>
    <li>How to increase productivity and stay happy,</li>
    <li><span>…more practical takeaways from various areas of Web design.</span></li>
    </ol>
    <p><a href="http://smashingconf.com/ny-2014/registration" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2014/01/get-the-tickets.png" width="270" height="103" alt="To the tickets" style="max-width: 100%; height: auto;"></a></p>
    <h3>Ticket Sales And Pricing</h3>
    <p>Only 350 tickets are available, and we do everything possible to keep our prices fair and affordable. The price for two full conference days is $549 for <strong>early-bird</strong> tickets, and $599 for regular tickets. And again, if you book a workshop as well, you’ll save $100. Yay! <a href="http://smashingconf.com/ny-2014/registration" rel="nofollow external" class="bo">Get your ticket right away.</a></p>
    <p><a title="8 reasons why you should send your incredibly hard-working, deserving employee to the SmashingConf" href="http://smashingconf.com/pdf/8-reasons-for-Smashing-Conference-NYC-2014.pdf" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2014/01/convince-boss-preview.png" width="450" height="288" alt="SmashingConf NY: Convince Your Boss PDF" style="max-width: 100%; height: auto;"></a><br><em>“8 reasons why you should send your incredibly hard-working, deserving employee to the SmashingConf” (<a href="http://smashingconf.com/pdf/8-reasons-for-Smashing-Conference-NYC-2014.pdf" rel="nofollow external" class="bo">PDF</a>). Quite self-explanatory, really.</em></p>
    <p>We also prepared a neat <a href="http://smashingconf.com/pdf/8-reasons-for-Smashing-Conference-NYC-2014.pdf" rel="nofollow external" class="bo">Convince Your Boss (PDF)</a> (0.15 Mb) that you can use to convince your colleagues, friends, neighbors and total strangers to join you or send you to the event. We <em>know</em> that you will <em>not</em> be disappointed. Still not good enough? Well, tweet us <em>@smashingconf</em> — we can be quite convincing, too!</p>
    <h3>We Welcome Lovely Sponsors, You Know</h3>
    <p>We do everything possible to keep ticket prices affordable for everyone, and we welcome sponsors to help us create a truly unique, unforgettable conference experience. And you can be a major part of it.</p>
    <p>We have quite a number of attractive and creative <a href="http://smashingconf.com/pdf/Sponsorship-Opportunities-Smashing-Conference-2014-New-York-City.pdf" rel="nofollow external" class="bo">sponsorship packages</a> for you, and we are also flexible and would love to adjust them to your needs. So if you’re interested, please <strong>email</strong> us at <a href="mailto:hello@smashingconf.com" rel="nofollow external" class="bo">hello@smashingconf.com</a> — we’d love for you to be involved!</p>
    <h3>See You In New York!</h3>
    <p>We are looking forward to seeing you in New York, and who knows, perhaps we <em>can</em> tackle more complex problems that we thought we would! See you there!</p>
    <p><a href="http://smashingconf.com/ny-2014/locations" rel="nofollow external" class="bo"><img src="http://media.smashingmagazine.com/wp-content/uploads/2014/01/timescenter.jpg" alt="Times Center" style="max-width: 100%; height: auto;"></a><br><em>The conference will take place in the lovely TimesCenter, right off Times Square in New York. It doesn’t get any more central than that. <a href="https://shop.smashingmagazine.com/smashing-conference-new-york-2014.html" rel="nofollow external" class="bo">Grab your ticket.</a></em></p>
    <hr>
    <p><small>© Vitaly Friedman for <a href="http://www.smashingmagazine.com" rel="nofollow external" class="bo">Smashing Magazine</a>, 2014.</small></p>
    </div>
]]>
</Body>
<Summary>        SmashingConf NYC 2014 won’t solve all complex problems, but once it’s over you’ll know how to conquer yours. Our new conference in New York has 1 track, 2 conference days, 7 workshops, 18...</Summary>
<Website>http://www.smashingmagazine.com/2014/01/28/smashing-conference-new-york-2014/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/40658/guest@my.umbc.edu/08d947b36a06b34da1916676b83c28b2/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>design</Tag>
<Tag>development</Tag>
<Tag>events</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 28 Jan 2014 08:00:21 -0500</PostedAt>
</NewsItem>

<NewsItem contentIssues="true" id="40659" important="false" status="posted" url="https://my3.my.umbc.edu/posts/40659">
<Title>The New Smashing Mystery Riddle: Have You Figured It Out Yet?</Title>
<Body>
<![CDATA[
    <div class="html-content">
    <table width="650">
    <tbody>
    <tr>
    <td>
    <div>
    <img src="http://statisches.auslieferung.commindo-media-ressourcen.de/advertisement.gif" alt="" style="max-width: 100%; height: auto;"><br><a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=1" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=1" alt="" style="max-width: 100%; height: auto;"></a> <a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=2" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=2" alt="" style="max-width: 100%; height: auto;"></a> <a href="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=target&amp;collection=smashing-rss&amp;position=3" rel="nofollow external" class="bo"><img src="http://auslieferung.commindo-media-ressourcen.de/random.php?mode=image&amp;collection=smashing-rss&amp;position=3" alt="" style="max-width: 100%; height: auto;"></a>
    </div>
    </td>
    </tr>
    </tbody>
    </table>
    <p>Remember the <a href="http://www.smashingmagazine.com/the-smashing-book-mystery-is-resolved-gifs-crazy-people-all-that-malarkey/" rel="nofollow external" class="bo">Smashing Book Mystery riddle</a> from a couple of months ago? Guess what: the Mystery continues! To celebrate the launch of the <a href="http://www.smashingmagazine.com/smashing-conference-new-york-2014/" rel="nofollow external" class="bo">SmashingConf NYC</a> and our lovely book, we’ve prepared a new riddle, and this time it’s not going to be any easier, but the reward is definitely worth the effort.</p>
    <p>How does it work? Below you’ll find an <strong>animated GIF that contains a hidden message</strong>. Once you resolved the mystery, you’ll see a Twitter hashtag displayed in plain text.</p>
    <p>Are you ready? Action! (<em>Hint: watch out for the file name</em>).</p>
    <p><img alt="Smashing Book Mystery" src="http://provide.smashingmagazine.com/mystery-riddle/catch-the-birds.gif" style="max-width: 100%; height: auto;"><br>
    <em>A hint: watch out for the file name.</em></p>
    <h3>What Can You Win?</h3>
    <p>Among the first readers who tweet us with the hidden hashtag, we’ll raffle a quite extraordinary, <em>smashing</em> prize (and a couple of other Smashing extras):</p>
    <ul>
    <li>a <strong>roundtrip flight to New York, USA</strong>,</li>
    <li>full accommodation in a fancy hotel,</li>
    <li>a ticket to the <a href="http://www.smashingconf.com/ny-2014/" rel="nofollow external" class="bo">Smashing Conference New York 2014</a>,</li>
    <li>any Smashing workshop ticket of your choice,</li>
    <li>full access to the Smashing eBook Library,</li>
    <li>a signed edition of the <a href="https://shop.smashingmagazine.com/smashing-book-4-new-perspectives-on-web-design.html?pk_campaign=front-page-shop" rel="nofollow external" class="bo">Smashing Book #4</a>,</li>
    <li>a truly Smashing laptop bag,</li>
    <li>your very own Smashing caricature, designed just for you.</li>
    </ul>
    <p>Please notice that to avoid spoilers, comments are closed for this post. And sorry, we aren’t going to make it too easy for you.</p>
    <p>Alright. Let’s get to work. Or have you already figured it out? ;-)</p>
    <hr>
    <p><small>© Vitaly Friedman for <a href="http://www.smashingmagazine.com" rel="nofollow external" class="bo">Smashing Magazine</a>, 2014.</small></p>
    </div>
]]>
</Body>
<Summary>        Remember the Smashing Book Mystery riddle from a couple of months ago? Guess what: the Mystery continues! To celebrate the launch of the SmashingConf NYC and our lovely book, we’ve...</Summary>
<Website>http://www.smashingmagazine.com/2014/01/28/the-new-smashing-mystery-riddle-smashingconf-ny/</Website>
<TrackingUrl>https://my3.my.umbc.edu/api/v0/pixel/news/40659/guest@my.umbc.edu/f4743eb98b6b3fdaea2648c1758bc6ec/api/pixel</TrackingUrl>
<Tag>css</Tag>
<Tag>design</Tag>
<Tag>developers-toolbox</Tag>
<Tag>development</Tag>
<Tag>html</Tag>
<Tag>javascript</Tag>
<Tag>mysql</Tag>
<Tag>php</Tag>
<Tag>sql</Tag>
<Tag>web</Tag>
<Group token="retired-583">Web Developer - Build Group</Group>
<GroupUrl>https://my3.my.umbc.edu/groups/retired-583</GroupUrl>
<AvatarUrl>https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="original">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/original.jpg?1363101197</AvatarUrl>
<AvatarUrl size="xxlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="xlarge">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xlarge.png?1363101197</AvatarUrl>
<AvatarUrl size="large">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/large.png?1363101197</AvatarUrl>
<AvatarUrl size="medium">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/medium.png?1363101197</AvatarUrl>
<AvatarUrl size="small">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/small.png?1363101197</AvatarUrl>
<AvatarUrl size="xsmall">https://assets3-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xsmall.png?1363101197</AvatarUrl>
<AvatarUrl size="xxsmall">https://assets4-my.umbc.edu/system/shared/avatars/groups/000/000/583/fc60f5d7abc2e080599bb6dc465db54d/xxsmall.png?1363101197</AvatarUrl>
<Sponsor>Web Developer - Build Group</Sponsor>
<PawCount>0</PawCount>
<CommentCount>0</CommentCount>
<CommentsAllowed>true</CommentsAllowed>
<PostedAt>Tue, 28 Jan 2014 08:00:11 -0500</PostedAt>
</NewsItem>

</News>
